From 342073f125cc55114733f71251e00e51f8e2803e Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Wed, 19 Oct 2022 21:20:38 +0200 Subject: [PATCH 01/11] feature: add wtf command for junifer --- junifer/api/cli.py | 21 +++++++++-- junifer/api/utils.py | 90 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 junifer/api/utils.py diff --git a/junifer/api/cli.py b/junifer/api/cli.py index 2402de4b9..5f034acf8 100644 --- a/junifer/api/cli.py +++ b/junifer/api/cli.py @@ -8,12 +8,20 @@ import pathlib from typing import Dict, List, Union import click +import yaml from ..utils.logging import configure_logging, logger, warn_with_log from .functions import collect as api_collect from .functions import queue as api_queue from .functions import run as api_run from .parser import parse_yaml +from .utils import ( + _get_dependency_information, + _get_environment_information, + _get_junifer_version, + _get_python_information, + _get_system_information, +) def _parse_elements(element: str, config: Dict) -> Union[List, None]: @@ -190,6 +198,13 @@ def queue( @cli.command() -def selftest() -> None: - """Selftest command for CLI.""" - pass +def wtf() -> None: + """Wtf command for CLI.""" + report = { + "junifer": _get_junifer_version(), + "python": _get_python_information(), + "dependencies": _get_dependency_information(), + "system": _get_system_information(), + "environment": _get_environment_information(), + } + click.echo(yaml.dump(report, sort_keys=False)) diff --git a/junifer/api/utils.py b/junifer/api/utils.py new file mode 100644 index 000000000..28511cd20 --- /dev/null +++ b/junifer/api/utils.py @@ -0,0 +1,90 @@ +"""Provide utility functions for the api sub-package.""" + +# Authors: Synchon Mandal +# License: AGPL + +import os +import platform as pl +from typing import Dict + +from .._version import __version__ +from ..utils.logging import get_versions + + +def _get_junifer_version() -> Dict[str, str]: + """Get junifer version information. + + Returns + ------- + dict + A dictionary containing junifer version. + + """ + return { + "version": __version__, + } + + +def _get_python_information() -> Dict[str, str]: + """Get installed Python information. + + Parameters + ---------- + dict + A dictionary containing Python information. + + """ + return { + "version": pl.python_version(), + "implementation": pl.python_implementation(), + } + + +def _get_dependency_information() -> Dict[str, str]: + """Get Python environment dependency information. + + Returns + ------- + dict + A dictionary containing Python dependency information. + + """ + dependency_versions = get_versions() + + pruned_dependency_versions = {} + for key in ["numpy", "scipy", "pandas", "nilearn", "nibabel", "nitime"]: + if key in dependency_versions.keys(): + pruned_dependency_versions[key] = dependency_versions[key] + + return pruned_dependency_versions + + +def _get_system_information() -> Dict[str, str]: + """Get system information. + + Returns + ------- + dict + A dictionary containing system information. + + """ + return { + "platform": pl.platform(), + } + + +def _get_environment_information() -> Dict[str, str]: + """Get system environment information. + + Returns + ------- + dict + A dictionary containing system environment information. + + """ + environment_values = {} + for key in ["LC_CTYPE", "LC_TERMINAL", "LC_TERMINAL_VERSION", "PATH"]: + if key in os.environ.keys(): + environment_values[key] = os.environ[key] + + return environment_values -- 2.52.0 From f5bc0dcf4acd6afa84f532d48ae583dff3bdfd24 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 09:12:40 +0200 Subject: [PATCH 02/11] update: allow all installed modules' report for dependencies --- junifer/api/utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 28511cd20..185449ca9 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -52,9 +52,10 @@ def _get_dependency_information() -> Dict[str, str]: dependency_versions = get_versions() pruned_dependency_versions = {} - for key in ["numpy", "scipy", "pandas", "nilearn", "nibabel", "nitime"]: - if key in dependency_versions.keys(): - pruned_dependency_versions[key] = dependency_versions[key] + for key, value in dependency_versions.items(): + # Ignore built-in modules and self + if value != "None" and key != "junifer": + pruned_dependency_versions[key] = value return pruned_dependency_versions -- 2.52.0 From 8b5fa113e1f9b83009a37ddb4d0ada6d5b687758 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 09:14:48 +0200 Subject: [PATCH 03/11] update: allow all environment variables' report --- junifer/api/utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 185449ca9..55037f7dc 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -84,8 +84,7 @@ def _get_environment_information() -> Dict[str, str]: """ environment_values = {} - for key in ["LC_CTYPE", "LC_TERMINAL", "LC_TERMINAL_VERSION", "PATH"]: - if key in os.environ.keys(): - environment_values[key] = os.environ[key] + for key, value in os.environ.items(): + environment_values[key] = value return environment_values -- 2.52.0 From ddb068457e971f473660fb7d1985ab6689cbf42d Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 11:49:42 +0200 Subject: [PATCH 04/11] update: add --long flag to junifer wtf --- junifer/api/cli.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/junifer/api/cli.py b/junifer/api/cli.py index 5f034acf8..bdc271c00 100644 --- a/junifer/api/cli.py +++ b/junifer/api/cli.py @@ -198,8 +198,16 @@ def queue( @cli.command() -def wtf() -> None: - """Wtf command for CLI.""" +@click.option("--long", "long_", is_flag=True) +def wtf(long_: bool) -> None: + """Wtf command for CLI. + + Parameters + ---------- + long_ : bool + Whether to report long version or not. + + """ report = { "junifer": _get_junifer_version(), "python": _get_python_information(), -- 2.52.0 From 05170fe60574ac2098a9565fe66118a41d24b1ae Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 11:50:08 +0200 Subject: [PATCH 05/11] update: modify _get_dependency_information() to have long and short versions --- junifer/api/cli.py | 2 +- junifer/api/utils.py | 32 +++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/junifer/api/cli.py b/junifer/api/cli.py index bdc271c00..ada677ba5 100644 --- a/junifer/api/cli.py +++ b/junifer/api/cli.py @@ -211,7 +211,7 @@ def wtf(long_: bool) -> None: report = { "junifer": _get_junifer_version(), "python": _get_python_information(), - "dependencies": _get_dependency_information(), + "dependencies": _get_dependency_information(long_=long_), "system": _get_system_information(), "environment": _get_environment_information(), } diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 55037f7dc..138d229af 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -40,9 +40,14 @@ def _get_python_information() -> Dict[str, str]: } -def _get_dependency_information() -> Dict[str, str]: +def _get_dependency_information(long_: bool) -> Dict[str, str]: """Get Python environment dependency information. + Parameters + ---------- + long_ : bool + Whether to report long version. + Returns ------- dict @@ -52,10 +57,27 @@ def _get_dependency_information() -> Dict[str, str]: dependency_versions = get_versions() pruned_dependency_versions = {} - for key, value in dependency_versions.items(): - # Ignore built-in modules and self - if value != "None" and key != "junifer": - pruned_dependency_versions[key] = value + # Report long version + if long_: + for key, value in dependency_versions.items(): + # Ignore built-in modules and self + if value != "None" and key != "junifer": + pruned_dependency_versions[key] = value + + # Report short version + else: + for key in [ + "click", + "numpy", + "datalad", + "pandas", + "nibabel", + "nilearn", + "sqlalchemy", + "pyyaml", + ]: + if key in dependency_versions.keys(): + pruned_dependency_versions[key] = dependency_versions[key] return pruned_dependency_versions -- 2.52.0 From 04aefea0e0b1099e405390cf2f626d8ffa305bdb Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 11:50:48 +0200 Subject: [PATCH 06/11] update: modify _get_environment_information() to have long and short versions --- junifer/api/cli.py | 2 +- junifer/api/utils.py | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/junifer/api/cli.py b/junifer/api/cli.py index ada677ba5..a5888ccbd 100644 --- a/junifer/api/cli.py +++ b/junifer/api/cli.py @@ -213,6 +213,6 @@ def wtf(long_: bool) -> None: "python": _get_python_information(), "dependencies": _get_dependency_information(long_=long_), "system": _get_system_information(), - "environment": _get_environment_information(), + "environment": _get_environment_information(long_=long_), } click.echo(yaml.dump(report, sort_keys=False)) diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 138d229af..1221ee092 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -96,9 +96,14 @@ def _get_system_information() -> Dict[str, str]: } -def _get_environment_information() -> Dict[str, str]: +def _get_environment_information(long_: bool) -> Dict[str, str]: """Get system environment information. + Parameters + ---------- + long_ : bool + Whether to report long version. + Returns ------- dict @@ -106,7 +111,14 @@ def _get_environment_information() -> Dict[str, str]: """ environment_values = {} - for key, value in os.environ.items(): - environment_values[key] = value + # Report long version + if long_: + for key, value in os.environ.items(): + environment_values[key] = value + # Report short version + else: + for key in ["LC_CTYPE", "LC_TERMINAL", "LC_TERMINAL_VERSION", "PATH"]: + if key in os.environ.keys(): + environment_values[key] = os.environ[key] return environment_values -- 2.52.0 From 6fd5b63e6407c1bdc311d2b1e561a1581fc76581 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 14:24:10 +0200 Subject: [PATCH 07/11] fix: correct name for PyYAML for dependency reporting --- junifer/api/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 1221ee092..78ea56779 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -74,7 +74,7 @@ def _get_dependency_information(long_: bool) -> Dict[str, str]: "nibabel", "nilearn", "sqlalchemy", - "pyyaml", + "yaml", ]: if key in dependency_versions.keys(): pruned_dependency_versions[key] = dependency_versions[key] -- 2.52.0 From dbe077de84d3240e32d97c8c6f1056d09cfe9bf3 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 14:24:36 +0200 Subject: [PATCH 08/11] update: add tests for junifer.api.utils --- junifer/api/tests/test_api_utils.py | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 junifer/api/tests/test_api_utils.py diff --git a/junifer/api/tests/test_api_utils.py b/junifer/api/tests/test_api_utils.py new file mode 100644 index 000000000..16d917be7 --- /dev/null +++ b/junifer/api/tests/test_api_utils.py @@ -0,0 +1,89 @@ +"""Provide tests for utils.""" + +# Authors: Synchon Mandal +# License: AGPL + +import platform as pl + +from junifer._version import __version__ +from junifer.api.utils import ( + _get_dependency_information, + _get_environment_information, + _get_junifer_version, + _get_python_information, + _get_system_information, +) + + +def test_get_junifer_version() -> None: + """Test _get_junifer_version().""" + assert _get_junifer_version()["version"] == __version__ + + +def test_get_python_information() -> None: + """Test _get_python_information().""" + python_information = _get_python_information() + assert python_information["version"] == pl.python_version() + assert python_information["implementation"] == pl.python_implementation() + + +def test_get_dependency_information_short() -> None: + """Test short version of _get_dependency_information().""" + dependency_information = _get_dependency_information(long_=False) + assert [key for key in dependency_information.keys()] == [ + "click", + "numpy", + "datalad", + "pandas", + "nibabel", + "nilearn", + "sqlalchemy", + "yaml", + ] + + +def test_get_dependency_information_long() -> None: + """Test long version of _get_dependency_information().""" + dependency_information = _get_dependency_information(long_=True) + dependency_information_keys = [ + key for key in dependency_information.keys() + ] + for key in [ + "click", + "numpy", + "datalad", + "pandas", + "nibabel", + "nilearn", + "sqlalchemy", + "yaml", + ]: + assert key in dependency_information_keys + + +def test_get_system_information() -> None: + """Test _get_system_information().""" + system_information = _get_system_information() + assert system_information["platform"] == pl.platform() + + +def test_get_environment_information_short() -> None: + """Test short version of _get_environment_information().""" + environment_information = _get_environment_information(long_=False) + assert [key for key in environment_information.keys()] == [ + "LC_CTYPE", + "PATH", + ] + + +def test_get_environment_information_long() -> None: + """Test long version of _get_environment_information().""" + environment_information = _get_environment_information(long_=True) + environment_information_keys = [ + key for key in environment_information.keys() + ] + for key in [ + "LC_CTYPE", + "PATH", + ]: + assert key in environment_information_keys -- 2.52.0 From 6359c3f35ffca84326f12082eacf83f5d45ffcc8 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 14:25:18 +0200 Subject: [PATCH 09/11] update: add tests for junifer.api.cli.wtf --- junifer/api/tests/test_cli.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/junifer/api/tests/test_cli.py b/junifer/api/tests/test_cli.py index 380196f12..e2259c581 100644 --- a/junifer/api/tests/test_cli.py +++ b/junifer/api/tests/test_cli.py @@ -11,7 +11,7 @@ import pytest import yaml from click.testing import CliRunner -from junifer.api.cli import collect, run +from junifer.api.cli import collect, run, wtf # Create click test runner @@ -68,3 +68,19 @@ def test_run_and_collect_commands( collect_result = runner.invoke(collect, collect_args) # Check assert collect_result.exit_code == 0 + + +def test_wtf_short() -> None: + """Test short version of wtf command.""" + # Invoke wtf command + wtf_result = runner.invoke(wtf) + # Check + assert wtf_result.exit_code == 0 + + +def test_wtf_long() -> None: + """Test long version of wtf command.""" + # Invoke wtf command + wtf_result = runner.invoke(wtf, "--long") + # Check + assert wtf_result.exit_code == 0 -- 2.52.0 From c4dd85a8fe30f4a2666dfbeb189ed8ce624b0b48 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 20 Oct 2022 16:01:09 +0200 Subject: [PATCH 10/11] fix: simplify testing for _get_environment_information() --- junifer/api/tests/test_api_utils.py | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/junifer/api/tests/test_api_utils.py b/junifer/api/tests/test_api_utils.py index 16d917be7..33dd4db42 100644 --- a/junifer/api/tests/test_api_utils.py +++ b/junifer/api/tests/test_api_utils.py @@ -5,6 +5,8 @@ import platform as pl +import pytest + from junifer._version import __version__ from junifer.api.utils import ( _get_dependency_information, @@ -67,23 +69,21 @@ def test_get_system_information() -> None: assert system_information["platform"] == pl.platform() -def test_get_environment_information_short() -> None: - """Test short version of _get_environment_information().""" - environment_information = _get_environment_information(long_=False) - assert [key for key in environment_information.keys()] == [ - "LC_CTYPE", - "PATH", - ] +@pytest.mark.parametrize( + "format_", + [ + "short", + "long", + ], +) +def test_get_environment_information(format_: str) -> None: + """Test _get_environment_information(). + Parameters + ---------- + format_ : str + The parametrized report version. -def test_get_environment_information_long() -> None: - """Test long version of _get_environment_information().""" - environment_information = _get_environment_information(long_=True) - environment_information_keys = [ - key for key in environment_information.keys() - ] - for key in [ - "LC_CTYPE", - "PATH", - ]: - assert key in environment_information_keys + """ + environment_information = _get_environment_information(long_=format_) + assert "PATH" in environment_information.keys() -- 2.52.0 From 80d95cb30dc0ce711a37630cc3b95e80ae3f5302 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 21 Oct 2022 12:16:28 +0200 Subject: [PATCH 11/11] fix: improve checking for installed modules in _get_dependency_information() --- junifer/api/utils.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/junifer/api/utils.py b/junifer/api/utils.py index 78ea56779..0cd5552a8 100644 --- a/junifer/api/utils.py +++ b/junifer/api/utils.py @@ -5,6 +5,8 @@ import os import platform as pl +import re +from importlib.metadata import distribution from typing import Dict from .._version import __version__ @@ -66,18 +68,24 @@ def _get_dependency_information(long_: bool) -> Dict[str, str]: # Report short version else: - for key in [ - "click", - "numpy", - "datalad", - "pandas", - "nibabel", - "nilearn", - "sqlalchemy", - "yaml", - ]: + # Get dependencies for junifer + dist = distribution("junifer") + # Compile regex pattern + re_pattern = re.compile("[a-z-]+") + + for pkg_with_version in dist.requires: + # Perform regex search + matches = re.findall(pattern=re_pattern, string=pkg_with_version) + # Fix issue with PyYAML name registration + if matches[0] == "pyyaml": + key = "yaml" + else: + key = matches[0] + if key in dependency_versions.keys(): - pruned_dependency_versions[key] = dependency_versions[key] + # Check if pkg part of optional dependencies + if "extra" not in matches: + pruned_dependency_versions[key] = dependency_versions[key] return pruned_dependency_versions -- 2.52.0