Package: auto-deprecator
Auto deprecatorDeprecation toolkit in PythonFree software: MIT licenseDocumentation:https://auto-deprecator.readthedocs.io.How does it work?The library provides the full cycle to deprecate a function in the following waysFor example, a function calledold_hello_worldshould be deprecated in the version 2.0.0, while the current version of the library is 1.0.0.Add a decoratordeprecateabove the function like the below can manage the mentioned deprecation cycle.fromauto_deprecatorimportdeprecate@deprecate(expiry='2.0.0',current='1.9.0')defold_hello_world():returnprint("Hello world!")defhello_world():returnprint("Hello world again!")You can also suggest the replacing function / method. For details, please refer to the sectionProvide hints to users.Warning StageAlert the users the deprecation timeWhen the user calls the methods or initializes the objects which will be deprecated
in the next version or on an expected date, the user should receive the warning of
the future deprecation but get the return in success. The default warning handler is to throw aDeprecationWarningand the handle method can be customized in the sectionCustomize the deprecation handling>>>old_hello_world()Helloworld!DeprecationWarning:Thefunction"old_hello_world"willbedeprecatedonversion2.0.0Test as if deprecatedBefore the component is deprecated, unit / integration testing should be run
to ensure the deprecation does not break the existing flow. Pass in the environment
variables in the testing to simulate that the version is deployed.(bash)hello-world-app
Hello world!
DeprecationWarning: The function "old_hello_world" will be deprecated in version 2.0.0(bash)DEPRECATED_VERSION=2.0.0 hello-world-app
Traceback (most recent call last):
 ...
RuntimeError: The function "old_hello_world" is deprecated in version 2.0.0Expired StageIf the current version has reached the function expiry version,
calling the deprecated function will trigger the exception by default.fromauto_deprecatorimportdeprecate__version__='2.0.0'@deprecate(expiry='2.0.0',current=__version__)defold_hello_world():returnprint("Hello world!")For example, the above function is called by the downstream
processafter-hello-world. The owner of the process is not
aware that the function should be deprecated and replaced by
another function, and the process is crashed by the default
exception. To work around the exception in the production,
before a proper fix is provided, the environment variableDEPRECATED_VERSIONcan be injected in the downstream process.DEPRECATED_VERSION=1.9after-hello-worldCleaning StageAutomatic deprecation before releaseDeprecating the functions is no longer a manual work. Every time before release,
run the commandauto-deprecateto remove the functions deprecated in the coming
version.$auto-deprecatehello_world.py--version2.0.0The command removes the functionold_hello_worldfrom the source codes as the expiry version is 2.0.0. Also, if the source file does not require to import theauto-deprecateanymore (as all the functions have already been deprecated), the import line will be removed as well.$gitdifftool-y-xsdifffrom auto_deprecator import deprecate                         <
                                                              <
                                                              <
@deprecate(expiry='2.0.0', current='1.9.0')                   <
def old_hello_world():                                        <
    return print("Hello world!")                              <
                                                              <
                                                              <
def hello_world():                                              def hello_world():
    return print("Hello world again!")                        /     return print("Hello world again!")The function with a comment line to state the expiry version is
another way to inform the scriptauto-deprecateto remove the
part of the code when it is expired. For example,defold_hello_world():# auto-deprecate: expiry=2.0.0print('hello world')For the details of the comment hints, please refer to the sectionAuto deprecation hints in comments.InstallationThe library can be easily installed with pippip install auto-deprecatorAlternative InstallationIf the auto-deprecator is included and the functions are
well deprecated (following the whole cycle mentioned above),
your software does not need auto-deprecator anymore. For
developers who are not comfortable to include a library not
always in use as a dependency, they can just clone the source
code into your project instead.For example, your Python project contains a module called
“utils” to maintain all the utility functions..
├── setup.py
└── test_py_project
    ├── cli.py
    ├── __init__.py
    ├── test_py_project.py
    └── utils
        └── __init__.pyWith the bash command “curl”,curl https://raw.githubusercontent.com/auto-deprecator/auto-deprecator/develop/auto_deprecator/__init__.py -o $DESTthe source code of auto-deprecator can be cloned into the
target directory, i.e. “test_py_project/utils” in the examplecurl https://raw.githubusercontent.com/auto-deprecator/auto-deprecator/develop/auto_deprecator/__init__.py -o test_py_project/utils/auto_deprecator.pyFeaturesProvide hints to usersProvide the parameter “relocate”, the warning / error message will inform the user about
the relocated method.@deprecate(expiry='2.1.0',current='2.0.0',relocate='new_compute_method')defcompute_method():return'hello world'>>>old_hello_world()Helloworld!DeprecationWarning:Thefunction"old_hello_world"willbedeprecatedonversion2.0.0..Pleaseusemethod/function"new_compute_method".Import current version from module nameInstead of importing the version (__version__) in the module,fromyour_packageimport__version__@deprecate(expiry='2.1.0',current=__version__)defcompute_method():return'hello world'specifying the module name, which includes the version attribute, can
help maintain the source code in a clean manner.@deprecate(expiry='2.1.0',version_module='your_package')defcompute_method():return'hello world'Especially if the function is removed by the actionauto-deprecate,
the unused import will not be left in the module.Customize the deprecation handlingBy default, thedeprecatedecorator raiseDeprecationWarningfor the future expiry andRuntimeErroron the expiration. The behavior can be modified so as to fit in the infrastructure / production environment.For example, theDeprecationWarningcan be replaced by a simple print out by injecting a callable function into the parameterwarn_handler.@deprecate(expiry='2.1.0',current='2.0.0',warn_handler=print)defcompute_method():return'hello world'Same for injecting a callable function into the parametererror_handler, the behavior is replaced if the function is deprecated.Auto deprecation hints in commentsThe auto deprecation script handles not only the expiry parts wrapped by the decorator, but also those stated with comments.
The comment line in the format#auto-deprecate:expiry=<version>in the scope of the function or class is treated same as the
decorator hints@deprecate(expiry="version",...).For example, the below function will be removed# hello_world.pydefold_hello_world():# auto-deprecate: expiry=2.0.0print('hello world')when the script is called with current version greater than 2.0.0$auto-deprecatehello_world.py--version2.1.0History2020.4.0 (2020-04-23)Support deprecation hints in commentsSimplify the project architecture2020.3.0 (2020-04-11)Support automatic deprecation in the directorySupport customizing the deprecation handler2020.2.0 (2020-02-11)Introduce parameter version_module in the deprecate decorator, to
import the version dynamicallyRemoved magic version import2010.1.0, 2010.1.1, 2010.1.2 (2020-01-21)Support alerting the users the deprecate versionSupport testing with environment variablesSupport automatically deprecate the expiry source code