diff options
Diffstat (limited to 'logilab/common/deprecation.py')
-rw-r--r-- | logilab/common/deprecation.py | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py index 15f8087..a57ae33 100644 --- a/logilab/common/deprecation.py +++ b/logilab/common/deprecation.py @@ -45,7 +45,7 @@ class DeprecationWrapper(object): setattr(self._proxied, attr, value) -def _get_package_name(number=2): +def _get_module_name(number=1): """ automagically try to determine the package name from which the warning has been triggered by loop other calling frames. @@ -55,29 +55,27 @@ def _get_package_name(number=2): frame = sys._getframe() - for i in range(number): + for i in range(number + 1): if frame.f_back is None: break frame = frame.f_back - if frame.f_globals["__package__"] is not None: + if frame.f_globals["__package__"]: return frame.f_globals["__package__"] file_name = os.path.split(frame.f_globals["__file__"])[1] if file_name.endswith(".py"): - file_name = file_name[:-len(".py")] + file_name = file_name[: -len(".py")] return file_name -def send_warning(reason, version=None, stacklevel=2): +def send_warning(reason, version=None, stacklevel=2, module_name=None): """Display a deprecation message only if the version is older than the compatible version. """ - module_name = _get_package_name(stacklevel + 1) - if module_name and version: reason = '[%s %s] %s' % (module_name, version, reason) elif module_name: @@ -102,10 +100,15 @@ def callable_renamed(old_name, new_function, version=None): """ @wraps(new_function) def wrapped(*args, **kwargs): - send_warning(( - f"{old_name} has been renamed and is deprecated, uses {new_function.__name__} " - f"instead" - ), stacklevel=3, version=version) + send_warning( + ( + f"{old_name} has been renamed and is deprecated, uses {new_function.__name__} " + f"instead" + ), + stacklevel=3, + version=version, + module_name=new_function.__module__, + ) return new_function(*args, **kwargs) return wrapped @@ -129,8 +132,13 @@ def argument_removed(old_argument_name, version=None): @wraps(func) def check_kwargs(*args, **kwargs): if old_argument_name in kwargs: - send_warning(f"argument {old_argument_name} of callable {func.__name__} has been " - f"removed and is deprecated", stacklevel=3, version=version) + send_warning( + f"argument {old_argument_name} of callable {func.__name__} has been " + f"removed and is deprecated", + stacklevel=3, + version=version, + module_name=func.__module__, + ) del kwargs[old_argument_name] return func(*args, **kwargs) @@ -153,7 +161,7 @@ def callable_deprecated(reason=None, version=None, stacklevel=2): @wraps(func) def wrapped(*args, **kwargs): - send_warning(message, version, stacklevel + 1) + send_warning(message, version, stacklevel + 1, module_name=func.__module__) return func(*args, **kwargs) return wrapped @@ -167,10 +175,15 @@ class class_deprecated(type): """metaclass to print a warning on instantiation of a deprecated class""" def __call__(cls, *args, **kwargs): - msg = getattr(cls, "__deprecation_warning__", - "%(cls)s is deprecated") % {'cls': cls.__name__} - send_warning(msg, stacklevel=getattr(cls, "__deprecation_warning_stacklevel__", 4), - version=getattr(cls, "__deprecation_warning_version__", None)) + msg = getattr(cls, "__deprecation_warning__", "%(cls)s is deprecated") % { + "cls": cls.__name__ + } + send_warning( + msg, + stacklevel=getattr(cls, "__deprecation_warning_stacklevel__", 3), + version=getattr(cls, "__deprecation_warning_version__", None), + module_name=getattr(cls, "__deprecation_warning_module_name__", cls.__module__), + ) return type.__call__(cls, *args, **kwargs) @@ -201,15 +214,15 @@ def attribute_renamed(old_name, new_name, version=None): ) def _get_old(self): - send_warning(reason, stacklevel=3, version=version) + send_warning(reason, stacklevel=3, version=version, module_name=klass.__module__) return getattr(self, new_name) def _set_old(self, value): - send_warning(reason, stacklevel=3, version=version) + send_warning(reason, stacklevel=3, version=version, module_name=klass.__module__) setattr(self, new_name, value) def _del_old(self): - send_warning(reason, stacklevel=3, version=version) + send_warning(reason, stacklevel=3, version=version, module_name=klass.__module__) delattr(self, new_name) setattr(klass, old_name, property(_get_old, _set_old, _del_old)) @@ -240,9 +253,13 @@ def argument_renamed(old_name, new_name, version=None): f"{new_name} has keyword arguments, only uses {new_name}") if old_name in kwargs: - send_warning(f"argument {old_name} of callable {func.__name__} has been renamed " - f"and is deprecated, use keyword argument {new_name} instead", - stacklevel=3, version=version) + send_warning( + f"argument {old_name} of callable {func.__name__} has been renamed " + f"and is deprecated, use keyword argument {new_name} instead", + stacklevel=3, + version=version, + module_name=func.__module__, + ) kwargs[new_name] = kwargs[old_name] del kwargs[old_name] @@ -271,7 +288,9 @@ def callable_moved(module_name, object_name, version=None, stacklevel=2): def callnew(*args, **kwargs): from logilab.common.modutils import load_module_from_name - send_warning(message, version=version, stacklevel=stacklevel + 1) + send_warning( + message, version=version, stacklevel=stacklevel + 1, module_name=_get_module_name(1) + ) m = load_module_from_name(module_name) return getattr(m, object_name)(*args, **kwargs) @@ -282,7 +301,7 @@ def callable_moved(module_name, object_name, version=None, stacklevel=2): moved = callable_renamed(old_name="moved", new_function=callable_moved) -def class_renamed(old_name, new_class, message=None, version=None): +def class_renamed(old_name, new_class, message=None, version=None, module_name=None): """automatically creates a class which fires a DeprecationWarning when instantiated. @@ -294,11 +313,16 @@ def class_renamed(old_name, new_class, message=None, version=None): """ class_dict = {} if message is None: - message = '%s is deprecated, use %s instead' % (old_name, new_class.__name__) + message = "%s is deprecated, use %s instead" % (old_name, new_class.__name__) - class_dict['__deprecation_warning__'] = message - class_dict['__deprecation_warning_version__'] = version - class_dict['__deprecation_warning_stacklevel__'] = 5 + class_dict["__deprecation_warning__"] = message + class_dict["__deprecation_warning_version__"] = version + class_dict["__deprecation_warning_stacklevel__"] = 3 + + if module_name: + class_dict["__deprecation_warning_module_name__"] = module_name + else: + class_dict["__deprecation_warning_module_name__"] = _get_module_name(1) return class_deprecated(old_name, (new_class,), class_dict) @@ -311,7 +335,12 @@ def class_moved(new_class, old_name=None, message=None, version=None): old_name = new_class.__name__ if message is None: - message = 'class %s is now available as %s.%s' % ( - old_name, new_class.__module__, new_class.__name__) + message = "class %s is now available as %s.%s" % ( + old_name, + new_class.__module__, + new_class.__name__, + ) + + module_name = _get_module_name(1) - return class_renamed(old_name, new_class, message=message) + return class_renamed(old_name, new_class, message=message, module_name=module_name) |