From 99686d8e13dc974f5b58be75fed75701f5bf2e35 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl <alexfikl@gmail.com> Date: Wed, 14 Oct 2020 10:34:21 -0500 Subject: [PATCH] add deprecate_keyword decorator --- pytools/__init__.py | 85 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/pytools/__init__.py b/pytools/__init__.py index 950e001..7c1052a 100644 --- a/pytools/__init__.py +++ b/pytools/__init__.py @@ -26,7 +26,7 @@ THE SOFTWARE. """ -from functools import reduce +from functools import reduce, wraps import operator import sys import logging @@ -174,6 +174,69 @@ F = TypeVar("F", bound=Callable[..., Any]) # }}} +# {{{ code maintenance + +class MovedFunctionDeprecationWrapper: + def __init__(self, f, deadline=None): + if deadline is None: + deadline = "the future" + + self.f = f + self.deadline = deadline + + def __call__(self, *args, **kwargs): + from warnings import warn + warn(f"This function is deprecated and will go away in {self.deadline}. " + f"Use {self.f.__module}.{self.f.__name__} instead.", + DeprecationWarning, stacklevel=2) + + return self.f(*args, **kwargs) + + +def deprecate_keyword(oldkey: str, + newkey: Optional[str] = None, *, + deadline: Optional[str] = None): + """Decorator used to deprecate function keyword arguments. + + :arg oldkey: deprecated argument name. + :arg newkey: new argument name that serves the same purpose, if any. + :arg deadline: expected time frame for the removal of the deprecated argument. + """ + from warnings import warn + + if deadline is None: + deadline = "the future" + + def wrapper(func): + @wraps(func) + def inner_wrapper(*args, **kwargs): + if oldkey in kwargs: + if newkey is None: + warn(f"The '{oldkey}' keyword is deprecated and will " + f"go away in {deadline}.", + DeprecationWarning, stacklevel=2) + else: + warn(f"The '{oldkey}' keyword is deprecated and will " + f"go away in {deadline}. " + f"Use '{newkey}' instead.", + DeprecationWarning, stacklevel=2) + + if newkey in kwargs: + raise ValueError(f"Cannot use '{oldkey}' " + f"and '{newkey}' in the same call.") + + kwargs[newkey] = kwargs[oldkey] + del kwargs[oldkey] + + return func(*args, **kwargs) + + return inner_wrapper + + return wrapper + +# }}} + + # {{{ math -------------------------------------------------------------------- def delta(x, y): @@ -778,7 +841,6 @@ def memoize_method_nested(inner): "Use @memoize_in(self, 'identifier') instead", DeprecationWarning, stacklevel=2) - from functools import wraps cache_dict_name = intern("_memoize_inner_dic_%s_%s_%d" % (inner.__name__, inner.__code__.co_filename, inner.__code__.co_firstlineno)) @@ -827,8 +889,6 @@ class memoize_in(object): # noqa self.cache_dict = memoize_in_dict.setdefault(identifier, {}) def __call__(self, inner): - from functools import wraps - @wraps(inner) def new_inner(*args): try: @@ -1465,23 +1525,6 @@ def get_write_to_map_from_permutation(original, permuted): # }}} -# {{{ code maintenance - -class MovedFunctionDeprecationWrapper: - def __init__(self, f): - self.f = f - - def __call__(self, *args, **kwargs): - from warnings import warn - warn("This function is deprecated. Use %s.%s instead." % ( - self.f.__module__, self.f.__name__), - DeprecationWarning, stacklevel=2) - - return self.f(*args, **kwargs) - -# }}} - - # {{{ graph algorithms from pytools.graph import a_star as a_star_moved -- GitLab