From bc303a00a56845ca71e6fa81c7fe62f0b4cdfbfd Mon Sep 17 00:00:00 2001 From: Camille Troillard Date: Wed, 2 Oct 2024 13:52:23 +0200 Subject: [PATCH 1/3] feat: Add a convenient way of outputting system and dependency versions (#425) --- src/skore/__init__.py | 5 +- src/skore/utils/__init__.py | 1 + src/skore/utils/_show_versions.py | 82 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/skore/utils/__init__.py create mode 100644 src/skore/utils/_show_versions.py diff --git a/src/skore/__init__.py b/src/skore/__init__.py index 3b01c1474..3315055f6 100644 --- a/src/skore/__init__.py +++ b/src/skore/__init__.py @@ -1,4 +1,4 @@ -"""Provide the Store class for managing information in a data science project.""" +"""Configure logging and global settings.""" import logging @@ -6,8 +6,11 @@ from skore.project import Project, load +from .utils._show_versions import show_versions + __all__ = [ "load", + "show_versions", "Project", ] diff --git a/src/skore/utils/__init__.py b/src/skore/utils/__init__.py new file mode 100644 index 000000000..3ee290a4d --- /dev/null +++ b/src/skore/utils/__init__.py @@ -0,0 +1 @@ +"""Various utilities to help with development.""" diff --git a/src/skore/utils/_show_versions.py b/src/skore/utils/_show_versions.py new file mode 100644 index 000000000..8d5d60d26 --- /dev/null +++ b/src/skore/utils/_show_versions.py @@ -0,0 +1,82 @@ +""" +Utility methods to print system info for debugging. + +adapted from :func:`sklearn.show_versions` +""" + +import platform +import sys + + +def _get_sys_info(): + """System information. + + Returns + ------- + sys_info : dict + system and Python version information + + """ + python = sys.version.replace("\n", " ") + + blob = [ + ("python", python), + ("executable", sys.executable), + ("machine", platform.platform()), + ] + + return dict(blob) + + +def _get_deps_info(): + """Overview of the installed version of main dependencies. + + This function does not import the modules to collect the version numbers + but instead relies on standard Python package metadata. + + Returns + ------- + deps_info: dict + version information on relevant Python libraries + + """ + from importlib.metadata import PackageNotFoundError, version + + import tomllib + + deps = ["pip", "setuptools"] + + with open("pyproject.toml", "rb") as f: + data = tomllib.load(f) + deps += data["project"]["dependencies"] + + deps_info = { + "skore": version("skore"), + } + + for modname in deps: + try: + deps_info[modname] = version(modname) + except PackageNotFoundError: + deps_info[modname] = None + return deps_info + + +def show_versions(): + """Print useful debugging information. + + Examples + -------- + >>> from skore import show_versions + >>> show_versions() # doctest: +SKIP + """ + sys_info = _get_sys_info() + deps_info = _get_deps_info() + + print("\nSystem:") # noqa: T201 + for k, stat in sys_info.items(): + print(f"{k:>10}: {stat}") # noqa: T201 + + print("\nPython dependencies:") # noqa: T201 + for k, stat in deps_info.items(): + print(f"{k:>13}: {stat}") # noqa: T201 From 547aa362f45a4ac563a2dd8ef53dd62a3b433224 Mon Sep 17 00:00:00 2001 From: Matthieu Jouis Date: Thu, 3 Oct 2024 10:06:42 +0200 Subject: [PATCH 2/3] add tests for the show_versions function and make it work from any working directory --- src/skore/utils/_show_versions.py | 4 ++- tests/unit/utils/test_show_versions.py | 46 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/unit/utils/test_show_versions.py diff --git a/src/skore/utils/_show_versions.py b/src/skore/utils/_show_versions.py index 8d5d60d26..9f15d0d40 100644 --- a/src/skore/utils/_show_versions.py +++ b/src/skore/utils/_show_versions.py @@ -6,6 +6,7 @@ import platform import sys +from pathlib import Path def _get_sys_info(): @@ -46,7 +47,8 @@ def _get_deps_info(): deps = ["pip", "setuptools"] - with open("pyproject.toml", "rb") as f: + pyproject_path = Path(__file__).parent.parent.parent.parent / "pyproject.toml" + with open(pyproject_path, "rb") as f: data = tomllib.load(f) deps += data["project"]["dependencies"] diff --git a/tests/unit/utils/test_show_versions.py b/tests/unit/utils/test_show_versions.py new file mode 100644 index 000000000..13ed68889 --- /dev/null +++ b/tests/unit/utils/test_show_versions.py @@ -0,0 +1,46 @@ +import os +import tempfile + +from skore.utils._show_versions import _get_deps_info, _get_sys_info, show_versions + + +def test_get_sys_info(): + sys_info = _get_sys_info() + assert isinstance(sys_info, dict) + assert "python" in sys_info + assert "executable" in sys_info + assert "machine" in sys_info + + +def test_get_deps_info(): + deps_info = _get_deps_info() + assert isinstance(deps_info, dict) + assert "pip" in deps_info + assert "setuptools" in deps_info + assert "skore" in deps_info + + +def test_show_versions(capfd): + show_versions() + captured = capfd.readouterr() + assert "python" in captured.out + assert "executable" in captured.out + assert "machine" in captured.out + assert "pip" in captured.out + assert "setuptools" in captured.out + assert "skore" in captured.out + + +def test_get_deps_in_any_working_directory(capfd): + cwd = os.getcwd() + with tempfile.TemporaryDirectory() as temp_dir: + os.chdir(temp_dir) + show_versions() + captured = capfd.readouterr() + assert "python" in captured.out + assert "executable" in captured.out + assert "machine" in captured.out + assert "pip" in captured.out + assert "setuptools" in captured.out + assert "skore" in captured.out + os.chdir(cwd) From 3c69c0db17f9d023cf9946d06860803fea8f413e Mon Sep 17 00:00:00 2001 From: Matthieu Jouis Date: Thu, 3 Oct 2024 10:31:41 +0200 Subject: [PATCH 3/3] use importlib to get dependencies --- src/skore/utils/_show_versions.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/skore/utils/_show_versions.py b/src/skore/utils/_show_versions.py index 9f15d0d40..bfac99942 100644 --- a/src/skore/utils/_show_versions.py +++ b/src/skore/utils/_show_versions.py @@ -4,9 +4,9 @@ adapted from :func:`sklearn.show_versions` """ +import importlib import platform import sys -from pathlib import Path def _get_sys_info(): @@ -43,14 +43,11 @@ def _get_deps_info(): """ from importlib.metadata import PackageNotFoundError, version - import tomllib - deps = ["pip", "setuptools"] - pyproject_path = Path(__file__).parent.parent.parent.parent / "pyproject.toml" - with open(pyproject_path, "rb") as f: - data = tomllib.load(f) - deps += data["project"]["dependencies"] + requirements = importlib.metadata.requires("skore") + for requirement in filter(lambda r: "; extra" not in r, requirements): + deps.append(requirement) deps_info = { "skore": version("skore"),