From 2e8d887b1133620621d4b496f4d74fb45a0269d1 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Fri, 21 Nov 2025 16:50:41 -0500 Subject: [PATCH 1/3] deprecator decorator --- src/diffpy/utils/_deprecator.py | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/diffpy/utils/_deprecator.py diff --git a/src/diffpy/utils/_deprecator.py b/src/diffpy/utils/_deprecator.py new file mode 100644 index 0000000..1334de1 --- /dev/null +++ b/src/diffpy/utils/_deprecator.py @@ -0,0 +1,78 @@ +import functools +import warnings + +# Deprecated decorator is available for Python 3.13+, once +# Support for earlier versions is dropped, this custom implementation can be removed. +try: + from warnings import deprecated as _builtin_deprecated +except ImportError: + _builtin_deprecated = None + +def deprecated(*, alt_name=None, message=None): + """ + Marks a function or class as deprecated. + + Emits a DeprecationWarning whenever the decorated function is called + or the decorated class is instantiated. + + Parameters + ---------- + alt_name : str, optional + Name of the recommended alternative. + message : str, optional + Custom deprecation message. If None, a default message is generated. + + Returns + ------- + decorator : function + Decorator that wraps the deprecated object. + + Examples + -------- + .. code-block:: python + + from diffpy._deprecations import deprecated + + # ------------------------------ + # Deprecated function + # ------------------------------ + @deprecated(alt_name="new_function") + def old_function(x, y): + return x + y + + def new_function(x, y): + return x + y + + # Usage + old_function(1, 2) # Emits DeprecationWarning + new_function(1, 2) # No warning + + # ------------------------------ + # Deprecated class + # ------------------------------ + @deprecated(alt_name="NewAtom") + class OldAtom: + def __init__(self, symbol): + self.symbol = symbol + + # Usage + a = OldAtom("C") # Emits DeprecationWarning + atom = NewAtom("C") # No warning + """ + if _builtin_deprecated: + return _builtin_deprecated + + def decorator(obj): + name = getattr(obj, "__name__", repr(obj)) + msg = message or (f"'{name}' is deprecated. Use '{alt_name}' instead." + if alt_name else f"'{name}' is deprecated.") + + if callable(obj): + @functools.wraps(obj) + def wrapper(*args, **kwargs): + warnings.warn(msg, DeprecationWarning, stacklevel=2) + return obj(*args, **kwargs) + return wrapper + else: + raise TypeError("deprecated decorator can only be applied to functions or classes") + return decorator From 614b234383a47d3307a7b91e53e8ffe062e6515c Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Fri, 21 Nov 2025 16:51:52 -0500 Subject: [PATCH 2/3] precommit fixes --- src/diffpy/utils/_deprecator.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/diffpy/utils/_deprecator.py b/src/diffpy/utils/_deprecator.py index 1334de1..099e371 100644 --- a/src/diffpy/utils/_deprecator.py +++ b/src/diffpy/utils/_deprecator.py @@ -2,15 +2,16 @@ import warnings # Deprecated decorator is available for Python 3.13+, once -# Support for earlier versions is dropped, this custom implementation can be removed. +# Support for earlier versions is dropped, this custom +# implementation can be removed. try: from warnings import deprecated as _builtin_deprecated except ImportError: _builtin_deprecated = None + def deprecated(*, alt_name=None, message=None): - """ - Marks a function or class as deprecated. + """Marks a function or class as deprecated. Emits a DeprecationWarning whenever the decorated function is called or the decorated class is instantiated. @@ -64,15 +65,24 @@ def __init__(self, symbol): def decorator(obj): name = getattr(obj, "__name__", repr(obj)) - msg = message or (f"'{name}' is deprecated. Use '{alt_name}' instead." - if alt_name else f"'{name}' is deprecated.") + msg = message or ( + f"'{name}' is deprecated. Use '{alt_name}' instead." + if alt_name + else f"'{name}' is deprecated." + ) if callable(obj): + @functools.wraps(obj) def wrapper(*args, **kwargs): warnings.warn(msg, DeprecationWarning, stacklevel=2) return obj(*args, **kwargs) + return wrapper else: - raise TypeError("deprecated decorator can only be applied to functions or classes") + raise TypeError( + "deprecated decorator can only be applied to functions or " + "classes" + ) + return decorator From 4ec1cf22ee3202964d7ac4922b8868e91dd5fe42 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Fri, 21 Nov 2025 16:52:38 -0500 Subject: [PATCH 3/3] news --- news/deprecator.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/deprecator.rst diff --git a/news/deprecator.rst b/news/deprecator.rst new file mode 100644 index 0000000..dabbfdf --- /dev/null +++ b/news/deprecator.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add ``@deprecated`` decorator. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +*