From 452119641c5319cfa4f88e411801c6f2f3d0a3c2 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Thu, 2 Nov 2023 23:18:47 -0400 Subject: [PATCH 01/14] Simple framework to port scripts into legacy --- scilpy/version.py | 2 +- scripts/legacy/__init__.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 scripts/legacy/__init__.py diff --git a/scilpy/version.py b/scilpy/version.py index a79c64e19..0c52ffb5f 100644 --- a/scilpy/version.py +++ b/scilpy/version.py @@ -82,6 +82,6 @@ MINOR = _version_minor MICRO = _version_micro VERSION = __version__ -SCRIPTS = glob.glob("scripts/*.py") +SCRIPTS = glob.glob("scripts/*.py") + glob.glob("scripts/legacy/*.py") PREVIOUS_MAINTAINERS=["Jean-Christophe Houde"] diff --git a/scripts/legacy/__init__.py b/scripts/legacy/__init__.py new file mode 100644 index 000000000..e69de29bb From ad56893f75eca65ebf365f8d054c7ab372159b80 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 11:36:31 -0500 Subject: [PATCH 02/14] remove init from imported scripts --- scilpy/version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scilpy/version.py b/scilpy/version.py index 0c52ffb5f..beab40bdf 100644 --- a/scilpy/version.py +++ b/scilpy/version.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import glob +import os # Format expected by setup.py and doc/source/conf.py: string of form "X.Y.Z" _version_major = 1 @@ -82,6 +83,7 @@ MINOR = _version_minor MICRO = _version_micro VERSION = __version__ -SCRIPTS = glob.glob("scripts/*.py") + glob.glob("scripts/legacy/*.py") +SCRIPTS = filter(lambda s: not os.path.basename(s) == "__init__.py", + glob.glob("scripts/*.py") + glob.glob("scripts/legacy/*.py")) PREVIOUS_MAINTAINERS=["Jean-Christophe Houde"] From 309d8a38b90fa769fa78f009040cec2abb029954 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:05:37 -0500 Subject: [PATCH 03/14] Working decorator for scilpy. Need to work on the detection at build, not working --- requirements.txt | 3 ++- scilpy/io/deprecator.py | 20 ++++++++++++++++++++ scilpy/version.py | 5 ++++- setup.py | 39 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 scilpy/io/deprecator.py diff --git a/requirements.txt b/requirements.txt index 85b83b0a6..435e4bd3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,7 @@ fury==0.8.* future==0.18.* GitPython==3.1.* h5py==3.7.* +importlib==1.0.* joblib==1.2.* kiwisolver==1.4.* matplotlib==3.6.* @@ -22,6 +23,7 @@ nibabel==4.0.* nilearn==0.9.* numpy==1.23.* openpyxl==3.0.* +packaging == 23.2.* Pillow==10.0.* pybids==0.15.* pyparsing==3.0.* @@ -41,7 +43,6 @@ trimeshpy==0.0.2 vtk==9.2.* # Dipy requirements h5py>=2.8.0 -packaging>=19.0 tqdm>=4.30.0 -e git+https://github.com/scilus/hot_dipy@1.8.0.dev0#egg=dipy \ No newline at end of file diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py new file mode 100644 index 000000000..74c0fd0e8 --- /dev/null +++ b/scilpy/io/deprecator.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from dipy.utils.deprecator import deprecate_with_version, cmp_pkg_version +from functools import partial +from importlib import metadata +from packaging.version import parse + + +DEFAULT_DEPRECATION_WINDOW = 1 # Wait for 1 major release + # before forcing script removal + + +def deprecate_script(message, from_version): + # Get scilpy version using importlib, requires to wrap dipy comparator + _version_cmp = partial(cmp_pkg_version, + pkg_version_str=metadata.version('scilpy')) + + _v = parse(from_version).major + DEFAULT_DEPRECATION_WINDOW + return deprecate_with_version(message, version_comparator=_version_cmp, + since=from_version, until=f"{_v}.0.0") diff --git a/scilpy/version.py b/scilpy/version.py index beab40bdf..5a283f48e 100644 --- a/scilpy/version.py +++ b/scilpy/version.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +import itertools import glob import os @@ -83,7 +84,9 @@ MINOR = _version_minor MICRO = _version_micro VERSION = __version__ +LEGACY_SCRIPTS = filter(lambda s: not os.path.basename(s) == "__init__.py", + glob.glob("scripts/legacy/*.py")) SCRIPTS = filter(lambda s: not os.path.basename(s) == "__init__.py", - glob.glob("scripts/*.py") + glob.glob("scripts/legacy/*.py")) + glob.glob("scripts/*.py")) PREVIOUS_MAINTAINERS=["Jean-Christophe Houde"] diff --git a/setup.py b/setup.py index f77000a91..5e9cb22c4 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,9 @@ import os -from setuptools import setup, find_packages, Extension +from setuptools import setup, find_packages, Extension, Command from setuptools.command.build_ext import build_ext +from setuptools.command.install_scripts import install_scripts +from setuptools.errors import SetupError with open('requirements.txt') as f: required_dependencies = f.read().splitlines() @@ -27,6 +29,30 @@ def get_extensions(): return [uncompress, quick_tools, grid_intersections, streamlines_metrics] +class CheckScriptsDeprecationWindowCommand(install_scripts): + def run(self): + # Check if the scripts are still in the deprecated window + out_of_window_scripts = [] + print("hello world ! I will check your deprecated scripts !") + + for script in LEGACY_SCRIPTS: + try: + self.spawn([sys.executable, script, '--help']) + except Exception: + out_of_window_scripts.append(script) + + if len(out_of_window_scripts) > 0: + error_msg = ["Legacy scripts are out the deprecation window:"] + for script in out_of_window_scripts: + error_msg.append(" - {}".format(script)) + + error_msg.append("Please remove above scripts to resume the build") + + raise SetupError("\n".join(error_msg)) + + install_scripts.run(self) + + class CustomBuildExtCommand(build_ext): """ build_ext command to use when numpy headers are needed. """ @@ -64,7 +90,10 @@ def run(self): platforms=PLATFORMS, version=VERSION, packages=find_packages(), - cmdclass={'build_ext': CustomBuildExtCommand}, + cmdclass={ + 'build_ext': CustomBuildExtCommand, + 'install_scripts': CheckScriptsDeprecationWindowCommand + }, ext_modules=get_extensions(), python_requires=PYTHON_VERSION, setup_requires=['cython', 'numpy'], @@ -72,7 +101,10 @@ def run(self): entry_points={ 'console_scripts': ["{}=scripts.{}:main".format( os.path.basename(s), - os.path.basename(s).split(".")[0]) for s in SCRIPTS] + os.path.basename(s).split(".")[0]) for s in SCRIPTS] + \ + ["{}=scripts.legacy.{}:main".format( + os.path.basename(s), + os.path.basename(s).split(".")[0]) for s in LEGACY_SCRIPTS] }, data_files=[('data/LUT', ["data/LUT/freesurfer_desikan_killiany.json", @@ -81,3 +113,4 @@ def run(self): include_package_data=True) setup(**opts) +s override install-scripts \ No newline at end of file From 00b6c94366628fd728bb89fda880979e81162d99 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:07:08 -0500 Subject: [PATCH 04/14] remove for now --- setup.py | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/setup.py b/setup.py index 5e9cb22c4..3cef50ff1 100644 --- a/setup.py +++ b/setup.py @@ -29,30 +29,6 @@ def get_extensions(): return [uncompress, quick_tools, grid_intersections, streamlines_metrics] -class CheckScriptsDeprecationWindowCommand(install_scripts): - def run(self): - # Check if the scripts are still in the deprecated window - out_of_window_scripts = [] - print("hello world ! I will check your deprecated scripts !") - - for script in LEGACY_SCRIPTS: - try: - self.spawn([sys.executable, script, '--help']) - except Exception: - out_of_window_scripts.append(script) - - if len(out_of_window_scripts) > 0: - error_msg = ["Legacy scripts are out the deprecation window:"] - for script in out_of_window_scripts: - error_msg.append(" - {}".format(script)) - - error_msg.append("Please remove above scripts to resume the build") - - raise SetupError("\n".join(error_msg)) - - install_scripts.run(self) - - class CustomBuildExtCommand(build_ext): """ build_ext command to use when numpy headers are needed. """ @@ -91,8 +67,7 @@ def run(self): version=VERSION, packages=find_packages(), cmdclass={ - 'build_ext': CustomBuildExtCommand, - 'install_scripts': CheckScriptsDeprecationWindowCommand + 'build_ext': CustomBuildExtCommand }, ext_modules=get_extensions(), python_requires=PYTHON_VERSION, @@ -102,7 +77,7 @@ def run(self): 'console_scripts': ["{}=scripts.{}:main".format( os.path.basename(s), os.path.basename(s).split(".")[0]) for s in SCRIPTS] + \ - ["{}=scripts.legacy.{}:main".format( + ["{}=scripts.legacy.{}:main".format( os.path.basename(s), os.path.basename(s).split(".")[0]) for s in LEGACY_SCRIPTS] }, @@ -113,4 +88,3 @@ def run(self): include_package_data=True) setup(**opts) -s override install-scripts \ No newline at end of file From 69d9f024f6a35b17b98c66b5c968a88912e2a169 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:13:52 -0500 Subject: [PATCH 05/14] add setuptools to jenkins for importlib --- Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 57a7f6079..87651fb0f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,6 +12,7 @@ pipeline { pip3 install numpy==1.23.* pip3 install Cython==0.29.* pip3 install packaging==23.* + pip3 install setuptools pip3 install -e . ''' } @@ -27,6 +28,7 @@ pipeline { pip3 install wheel==0.38.* pip3 install numpy==1.23.* pip3 install packaging==23.* + pip3 install setuptools pip3 install -e . export MPLBACKEND="agg" export OPENBLAS_NUM_THREADS=1 From ab1b9f69480fd7435e907c6d571387761bf56d12 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:15:39 -0500 Subject: [PATCH 06/14] revert importlib --- Jenkinsfile | 2 -- requirements.txt | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 87651fb0f..57a7f6079 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,7 +12,6 @@ pipeline { pip3 install numpy==1.23.* pip3 install Cython==0.29.* pip3 install packaging==23.* - pip3 install setuptools pip3 install -e . ''' } @@ -28,7 +27,6 @@ pipeline { pip3 install wheel==0.38.* pip3 install numpy==1.23.* pip3 install packaging==23.* - pip3 install setuptools pip3 install -e . export MPLBACKEND="agg" export OPENBLAS_NUM_THREADS=1 diff --git a/requirements.txt b/requirements.txt index 435e4bd3a..b1a113ab9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,6 @@ fury==0.8.* future==0.18.* GitPython==3.1.* h5py==3.7.* -importlib==1.0.* joblib==1.2.* kiwisolver==1.4.* matplotlib==3.6.* @@ -32,7 +31,7 @@ pytest==7.2.* pytest-console-scripts==1.3.* pytest-mock==3.10.* python-dateutil==2.8.* -pytz==2022.6.* +pytz==2022.6.*pip3 install setuptools requests==2.28.* scikit-learn==1.2.* scipy==1.9.* From ba03f1bd97292c9c2012f18ec999eaf4e819b876 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:17:15 -0500 Subject: [PATCH 07/14] pep8 --- scilpy/io/deprecator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index 74c0fd0e8..ca0186e85 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -6,8 +6,8 @@ from packaging.version import parse -DEFAULT_DEPRECATION_WINDOW = 1 # Wait for 1 major release - # before forcing script removal +DEFAULT_DEPRECATION_WINDOW = 1 # Wait for 1 major release + # before forcing script removal def deprecate_script(message, from_version): From 4ddf228f648b6fb56589517ad32f92731807309d Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Mon, 13 Nov 2023 14:18:30 -0500 Subject: [PATCH 08/14] fix --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b1a113ab9..80ca73fc2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ pytest==7.2.* pytest-console-scripts==1.3.* pytest-mock==3.10.* python-dateutil==2.8.* -pytz==2022.6.*pip3 install setuptools +pytz==2022.6.* requests==2.28.* scikit-learn==1.2.* scipy==1.9.* From 59111ed672a0032a2a04198f28f4efc77172ba2c Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Tue, 14 Nov 2023 13:55:16 -0500 Subject: [PATCH 09/14] Deprecate scil_streamlines_math --- scilpy/io/deprecator.py | 11 ++++++++-- scripts/legacy/scil_streamlines_math.py | 28 +++++++++++++++++++++++++ scripts/scil_streamlines_math.py | 25 ---------------------- 3 files changed, 37 insertions(+), 27 deletions(-) create mode 100755 scripts/legacy/scil_streamlines_math.py delete mode 100755 scripts/scil_streamlines_math.py diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index ca0186e85..fbac62817 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -1,11 +1,17 @@ # -*- coding: utf-8 -*- -from dipy.utils.deprecator import deprecate_with_version, cmp_pkg_version +from dipy.utils.deprecator import (cmp_pkg_version, + deprecate_with_version, + ExpiredDeprecationError) from functools import partial from importlib import metadata from packaging.version import parse +class ScilpyExpiredDeprecation(ExpiredDeprecationError): + pass + + DEFAULT_DEPRECATION_WINDOW = 1 # Wait for 1 major release # before forcing script removal @@ -17,4 +23,5 @@ def deprecate_script(message, from_version): _v = parse(from_version).major + DEFAULT_DEPRECATION_WINDOW return deprecate_with_version(message, version_comparator=_version_cmp, - since=from_version, until=f"{_v}.0.0") + since=from_version, until=f"{_v}.0.0", + error_class=ScilpyExpiredDeprecation) diff --git a/scripts/legacy/scil_streamlines_math.py b/scripts/legacy/scil_streamlines_math.py new file mode 100755 index 000000000..31fc47fc9 --- /dev/null +++ b/scripts/legacy/scil_streamlines_math.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import warnings + +from scilpy.io.deprecator import deprecate_script +from scripts.scil_tractogram_math import main as new_main + + +DEPRECATION_MSG = """ + +*** WARNING *** + +This script will soon be renamed scil_tractogram_math.py. You should change +your existing pipelines accordingly. We will try to keep the following +convention: + +- Scripts on 'streamlines' treat each streamline individually. +- Scripts on 'tractograms' apply the same operation on all streamlines of the + tractogram. +""" + +@deprecate_script(DEPRECATION_MSG, '1.5.0') +def main(): + new_main() + + +if __name__ == "__main__": + main() diff --git a/scripts/scil_streamlines_math.py b/scripts/scil_streamlines_math.py deleted file mode 100755 index 3723fb159..000000000 --- a/scripts/scil_streamlines_math.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import warnings - -from scripts.scil_tractogram_math import main as new_main - - -def main(): - warnings.simplefilter('always', DeprecationWarning) - warnings.warn( - "\n\n*** WARNING ***\n" - "This script will soon be renamed scil_tractogram_math.py.\n" - "You should change your existing pipelines accordingly.\n" - "We will try to keep the following convention: Scripts on " - "'streamlines' treat each streamline individually.\nScripts on " - "'tractograms' apply the same operation on all streamlines of the " - "tractogram.\n\n", - DeprecationWarning, - stacklevel=3) - - new_main() - - -if __name__ == "__main__": - main() From 8067716dc721dd001808e25c288f51e3eb7e12cb Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Wed, 15 Nov 2023 16:09:48 -0500 Subject: [PATCH 10/14] Create our own deprecator. Expire on the minor version after 2 versions --- scilpy/io/deprecator.py | 110 +++++++++++++++++++++--- scripts/legacy/scil_streamlines_math.py | 5 +- 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index fbac62817..e84860a35 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -1,27 +1,111 @@ # -*- coding: utf-8 -*- -from dipy.utils.deprecator import (cmp_pkg_version, - deprecate_with_version, - ExpiredDeprecationError) -from functools import partial +from dipy.utils.deprecator import cmp_pkg_version, ExpiredDeprecationError +from functools import wraps from importlib import metadata from packaging.version import parse +import warnings + class ScilpyExpiredDeprecation(ExpiredDeprecationError): pass -DEFAULT_DEPRECATION_WINDOW = 1 # Wait for 1 major release +DEFAULT_SEPARATOR = "=" +DEFAULT_DEPRECATION_WINDOW = 2 # Wait for 2 minor releases # before forcing script removal +DEPRECATION_HEADER = f""" +{DEFAULT_SEPARATOR * 68} + +!!! WARNING !!! SCRIPT IS DEPRECATED AND WON'T BE AVAILABLE SOON !!! + +{DEFAULT_SEPARATOR * 68} +""" + + +DEPRECATION_FOOTER = """ +{SEPARATOR} + +{MESSAGE} + +AS OF VERSION {EXP_VERSION}, CALLING THIS SCRIPT WILL RAISE {EXP_ERROR}") + +{SEPARATOR} +""" + +EXPIRATION_FOOTER = """ +{SEPARATOR} + +{MESSAGE} + +SCRIPT {SCRIPT_NAME} HAS BEEN DEPRECATED SINCE {EXP_VERSION} + +{SEPARATOR} +""" + +def _separator(_msg): + _msg_width = max([len(_m) for _m in _msg.split("\n")]) + + return f"{DEFAULT_SEPARATOR * _msg_width}" + + +def _format_expiration_message(_script, _msg, _exp_version): + return EXPIRATION_FOOTER.format( + SCRIPT_NAME=_script, + MESSAGE=_msg, + EXP_VERSION=_exp_version, + SEPARATOR=_separator(EXPIRATION_FOOTER + _msg)) + + +def _format_deprecation_message(_msg, _exp_version): + _sep = DEPRECATION_FOOTER.format( + MESSAGE=_msg, + EXP_VERSION=_exp_version, + EXP_ERROR=ScilpyExpiredDeprecation, + SEPARATOR="") + + return DEPRECATION_FOOTER.format( + MESSAGE=_msg, + EXP_VERSION=_exp_version, + EXP_ERROR=ScilpyExpiredDeprecation, + SEPARATOR=_separator(_sep)) + + +def _warn(_exp_version, _msg, _func, *_args, **_kwargs): + warnings.simplefilter('always', DeprecationWarning) + warnings.warn(DEPRECATION_HEADER, DeprecationWarning, stacklevel=4) + + _error_to_raise = None + try: + _res = _func(*_args, **_kwargs) + except BaseException as e: + _error_to_raise = e + + warnings.warn(_format_deprecation_message(_msg, _exp_version), + DeprecationWarning, stacklevel=4) + + if _error_to_raise: + raise _error_to_raise + + return _res + + +def deprecate_script(script, message, from_version): + _from_version = parse(from_version) + _exp_minor = _from_version.minor + DEFAULT_DEPRECATION_WINDOW + _exp_version = f"{_from_version.major}.{_exp_minor}.0" -def deprecate_script(message, from_version): - # Get scilpy version using importlib, requires to wrap dipy comparator - _version_cmp = partial(cmp_pkg_version, - pkg_version_str=metadata.version('scilpy')) + def _deprecation_decorator(func): + @wraps(func) + def _wrapper(*args, **kwargs): + if cmp_pkg_version(metadata.version('scilpy'), _exp_version) > 0: + raise ScilpyExpiredDeprecation( + _format_expiration_message(script, message, _exp_version)) + else: + return _warn(_exp_version, message, func, *args, **kwargs) - _v = parse(from_version).major + DEFAULT_DEPRECATION_WINDOW - return deprecate_with_version(message, version_comparator=_version_cmp, - since=from_version, until=f"{_v}.0.0", - error_class=ScilpyExpiredDeprecation) + return _wrapper + + return _deprecation_decorator diff --git a/scripts/legacy/scil_streamlines_math.py b/scripts/legacy/scil_streamlines_math.py index 31fc47fc9..e04a098d2 100755 --- a/scripts/legacy/scil_streamlines_math.py +++ b/scripts/legacy/scil_streamlines_math.py @@ -6,8 +6,7 @@ from scripts.scil_tractogram_math import main as new_main -DEPRECATION_MSG = """ - +DEPRECATION_MSG = """\ *** WARNING *** This script will soon be renamed scil_tractogram_math.py. You should change @@ -19,7 +18,7 @@ tractogram. """ -@deprecate_script(DEPRECATION_MSG, '1.5.0') +@deprecate_script("scil_streamlines_math.py", DEPRECATION_MSG, '1.5.0') def main(): new_main() From 7fcddf3b25e9b8f70dd1d6f755d0fbeeeedfb241 Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Wed, 15 Nov 2023 22:03:33 -0500 Subject: [PATCH 11/14] pep8 fixes --- scilpy/io/deprecator.py | 7 +++---- scripts/legacy/scil_streamlines_math.py | 1 + setup.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index e84860a35..31d5d86eb 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -7,14 +7,12 @@ import warnings - class ScilpyExpiredDeprecation(ExpiredDeprecationError): pass DEFAULT_SEPARATOR = "=" -DEFAULT_DEPRECATION_WINDOW = 2 # Wait for 2 minor releases - # before forcing script removal +DEFAULT_DEPRECATION_WINDOW = 2 # Wait for 2 minor releases before rasing error DEPRECATION_HEADER = f""" {DEFAULT_SEPARATOR * 68} @@ -45,6 +43,7 @@ class ScilpyExpiredDeprecation(ExpiredDeprecationError): {SEPARATOR} """ + def _separator(_msg): _msg_width = max([len(_m) for _m in _msg.split("\n")]) @@ -107,5 +106,5 @@ def _wrapper(*args, **kwargs): return _warn(_exp_version, message, func, *args, **kwargs) return _wrapper - + return _deprecation_decorator diff --git a/scripts/legacy/scil_streamlines_math.py b/scripts/legacy/scil_streamlines_math.py index e04a098d2..a9158eb48 100755 --- a/scripts/legacy/scil_streamlines_math.py +++ b/scripts/legacy/scil_streamlines_math.py @@ -18,6 +18,7 @@ tractogram. """ + @deprecate_script("scil_streamlines_math.py", DEPRECATION_MSG, '1.5.0') def main(): new_main() diff --git a/setup.py b/setup.py index 3cef50ff1..4c368e7bf 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ def run(self): entry_points={ 'console_scripts': ["{}=scripts.{}:main".format( os.path.basename(s), - os.path.basename(s).split(".")[0]) for s in SCRIPTS] + \ + os.path.basename(s).split(".")[0]) for s in SCRIPTS] + ["{}=scripts.legacy.{}:main".format( os.path.basename(s), os.path.basename(s).split(".")[0]) for s in LEGACY_SCRIPTS] From 14b3fa1a5be3079197d07ec6e9a00313a5168e84 Mon Sep 17 00:00:00 2001 From: AlexVCaron Date: Wed, 15 Nov 2023 23:17:43 -0500 Subject: [PATCH 12/14] Cleanup deprecator. Reset expiration for scil_streamlines_math --- scilpy/io/deprecator.py | 118 +++++++++++------------- scripts/legacy/scil_streamlines_math.py | 9 +- 2 files changed, 57 insertions(+), 70 deletions(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index 31d5d86eb..a6c77af21 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -14,96 +14,86 @@ class ScilpyExpiredDeprecation(ExpiredDeprecationError): DEFAULT_SEPARATOR = "=" DEFAULT_DEPRECATION_WINDOW = 2 # Wait for 2 minor releases before rasing error -DEPRECATION_HEADER = f""" -{DEFAULT_SEPARATOR * 68} - -!!! WARNING !!! SCRIPT IS DEPRECATED AND WON'T BE AVAILABLE SOON !!! - -{DEFAULT_SEPARATOR * 68} +DEPRECATION_HEADER = """ +!!! WARNING !!! THIS SCRIPT IS DEPRECATED !!! """ - DEPRECATION_FOOTER = """ -{SEPARATOR} - -{MESSAGE} - -AS OF VERSION {EXP_VERSION}, CALLING THIS SCRIPT WILL RAISE {EXP_ERROR}") - -{SEPARATOR} +AS OF VERSION {EXP_VERSION}, CALLING THIS SCRIPT WILL RAISE {EXP_ERROR} """ EXPIRATION_FOOTER = """ -{SEPARATOR} +SCRIPT {SCRIPT_NAME} HAS BEEN REMOVED SINCE {EXP_VERSION} +""" +SEPARATOR_BLOCK = """ +{UP_SEPARATOR} {MESSAGE} - -SCRIPT {SCRIPT_NAME} HAS BEEN DEPRECATED SINCE {EXP_VERSION} - -{SEPARATOR} +{LOW_SEPARATOR} """ -def _separator(_msg): - _msg_width = max([len(_m) for _m in _msg.split("\n")]) - - return f"{DEFAULT_SEPARATOR * _msg_width}" - - -def _format_expiration_message(_script, _msg, _exp_version): - return EXPIRATION_FOOTER.format( - SCRIPT_NAME=_script, - MESSAGE=_msg, - EXP_VERSION=_exp_version, - SEPARATOR=_separator(EXPIRATION_FOOTER + _msg)) +def _block(_msg, _sep_len=80): + _sep = f"{DEFAULT_SEPARATOR * _sep_len}" + return SEPARATOR_BLOCK.format( + UP_SEPARATOR=_sep, MESSAGE=_msg, LOW_SEPARATOR=_sep) -def _format_deprecation_message(_msg, _exp_version): - _sep = DEPRECATION_FOOTER.format( - MESSAGE=_msg, - EXP_VERSION=_exp_version, - EXP_ERROR=ScilpyExpiredDeprecation, - SEPARATOR="") +def _header(_msg, _sep_len=80): + _sep = f"{DEFAULT_SEPARATOR * _sep_len}" + return SEPARATOR_BLOCK.format( + UP_SEPARATOR=_sep, MESSAGE=_msg, LOW_SEPARATOR="").rstrip("\n") - return DEPRECATION_FOOTER.format( - MESSAGE=_msg, - EXP_VERSION=_exp_version, - EXP_ERROR=ScilpyExpiredDeprecation, - SEPARATOR=_separator(_sep)) - -def _warn(_exp_version, _msg, _func, *_args, **_kwargs): +def _raise_warning(header, footer, func, *args, **kwargs): warnings.simplefilter('always', DeprecationWarning) - warnings.warn(DEPRECATION_HEADER, DeprecationWarning, stacklevel=4) + warnings.warn(header, DeprecationWarning, stacklevel=4) - _error_to_raise = None try: - _res = _func(*_args, **_kwargs) - except BaseException as e: - _error_to_raise = e - - warnings.warn(_format_deprecation_message(_msg, _exp_version), - DeprecationWarning, stacklevel=4) - - if _error_to_raise: - raise _error_to_raise - - return _res + return func(*args, **kwargs) + except: + raise + finally: + print("") + warnings.warn(footer, DeprecationWarning, stacklevel=4) def deprecate_script(script, message, from_version): - _from_version = parse(from_version) - _exp_minor = _from_version.minor + DEFAULT_DEPRECATION_WINDOW - _exp_version = f"{_from_version.major}.{_exp_minor}.0" + from_version = parse(from_version) + expiration_minor = from_version.minor + DEFAULT_DEPRECATION_WINDOW + expiration_version = f"{from_version.major}.{expiration_minor}.0" + current_version = metadata.version('scilpy') def _deprecation_decorator(func): @wraps(func) def _wrapper(*args, **kwargs): - if cmp_pkg_version(metadata.version('scilpy'), _exp_version) > 0: - raise ScilpyExpiredDeprecation( - _format_expiration_message(script, message, _exp_version)) + if cmp_pkg_version(current_version, expiration_version) > 0: + footer = f"""\ + {message} + {EXPIRATION_FOOTER.format( + SCRIPT_NAME=script, + EXP_VERSION=expiration_version)}\ + """ + + raise ScilpyExpiredDeprecation(f"""\ + {_header(DEPRECATION_HEADER)} + {_block(footer)} + """) else: - return _warn(_exp_version, message, func, *args, **kwargs) + header = DEPRECATION_HEADER + footer = f"""\ + {message} + {DEPRECATION_FOOTER.format( + EXP_VERSION=expiration_version, + EXP_ERROR=ScilpyExpiredDeprecation)}\ + """ + + msg_length = max( + len(_l) for _l in (header + footer).splitlines()) + + return _raise_warning(_block(header, msg_length), + _block(footer, msg_length), + func, *args, **kwargs) return _wrapper diff --git a/scripts/legacy/scil_streamlines_math.py b/scripts/legacy/scil_streamlines_math.py index a9158eb48..7e1fac95e 100755 --- a/scripts/legacy/scil_streamlines_math.py +++ b/scripts/legacy/scil_streamlines_math.py @@ -1,15 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import warnings from scilpy.io.deprecator import deprecate_script from scripts.scil_tractogram_math import main as new_main -DEPRECATION_MSG = """\ -*** WARNING *** - -This script will soon be renamed scil_tractogram_math.py. You should change +DEPRECATION_MSG = """ +This script has been renamed scil_tractogram_math.py. Please change your existing pipelines accordingly. We will try to keep the following convention: @@ -19,7 +16,7 @@ """ -@deprecate_script("scil_streamlines_math.py", DEPRECATION_MSG, '1.5.0') +@deprecate_script("scil_streamlines_math.py", DEPRECATION_MSG, '1.7.0') def main(): new_main() From 3cb2e36e94648b45530734c6497ff47c39c026da Mon Sep 17 00:00:00 2001 From: AlexVCaron Date: Wed, 15 Nov 2023 23:21:17 -0500 Subject: [PATCH 13/14] remove empty except --- scilpy/io/deprecator.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index a6c77af21..61048834a 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -51,8 +51,6 @@ def _raise_warning(header, footer, func, *args, **kwargs): try: return func(*args, **kwargs) - except: - raise finally: print("") warnings.warn(footer, DeprecationWarning, stacklevel=4) From cf3f3574a4972e684c521fbbb00e929bac3c109e Mon Sep 17 00:00:00 2001 From: Alex Valcourt Caron Date: Thu, 16 Nov 2023 13:27:27 -0500 Subject: [PATCH 14/14] fix version compare --- scilpy/io/deprecator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scilpy/io/deprecator.py b/scilpy/io/deprecator.py index 61048834a..d46ec1c81 100644 --- a/scilpy/io/deprecator.py +++ b/scilpy/io/deprecator.py @@ -65,7 +65,7 @@ def deprecate_script(script, message, from_version): def _deprecation_decorator(func): @wraps(func) def _wrapper(*args, **kwargs): - if cmp_pkg_version(current_version, expiration_version) > 0: + if cmp_pkg_version(current_version, expiration_version) >= 0: footer = f"""\ {message} {EXPIRATION_FOOTER.format(