diff --git a/baseclasses/__init__.py b/baseclasses/__init__.py index 5b23643..41f6d29 100644 --- a/baseclasses/__init__.py +++ b/baseclasses/__init__.py @@ -1,4 +1,4 @@ -__version__ = "1.8.5" +__version__ = "1.9.0" from .problems import ( AeroProblem, diff --git a/baseclasses/testing/__init__.py b/baseclasses/testing/__init__.py index 69ebece..638a9cb 100644 --- a/baseclasses/testing/__init__.py +++ b/baseclasses/testing/__init__.py @@ -1,4 +1,4 @@ from .pyRegTest import BaseRegTest, getTol -from .decorators import require_mpi +from .decorators import require_mpi, expire_deprecation -__all__ = ["BaseRegTest", "getTol", "require_mpi"] +__all__ = ["BaseRegTest", "getTol", "require_mpi", "expire_deprecation"] diff --git a/baseclasses/testing/decorators.py b/baseclasses/testing/decorators.py index ab15825..0138598 100644 --- a/baseclasses/testing/decorators.py +++ b/baseclasses/testing/decorators.py @@ -1,4 +1,8 @@ import functools +from importlib.metadata import version +from typing import Optional +import warnings +from packaging.version import Version import unittest from importlib.util import find_spec @@ -62,3 +66,44 @@ def skip_wrapper(*args, **kwargs): # module found, we just return the function and proceed normally else: return func + + +def expire_deprecation(package_name: str, removal_version: str, new_name: Optional[str] = None): + """Decorator for methods that have been deprecated and potentially replaced by a new method + + This decorator will raise a warning when the decorated method is called, and will raise an error if the current + version of the package is greater than or equal to the specified removal version, helping to ensure that deprecated + APIs are removed in a timely manner. + + Parameters + ---------- + package_name : str + _description_ + removal_version : str + _description_ + new_name : Optional[str], optional + _description_, by default None + """ + removal = Version(removal_version) + current = Version(version(package_name)) + + def decorator(func): + if current >= removal: + raise AssertionError( + f"{func.__qualname__}: deprecated API should have been " + f"removed in {package_name} v{removal} " + f"(current: v{current}). Please delete this shim." + ) + + msg = f"{func.__name__}() is deprecated and will be removed in {package_name} v{removal}." + if new_name is not None: + msg += f" Use {new_name} instead." + + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + warnings.warn(msg, DeprecationWarning, stacklevel=2) + return func(self, *args, **kwargs) + + return wrapper + + return decorator diff --git a/setup.py b/setup.py index ed103ff..0f86b96 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,7 @@ python_requires=">=3.11", install_requires=[ "numpy>=1.25", + "packaging", ], extras_require={ "docs": docs_require,