diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py index 9bea4009a14664513581974eb9692cee15aa47a0..b6c2b5ee5c090bd6b1ec5be9eac7b8fcce8d6169 100644 --- a/logilab/common/deprecation.py +++ b/logilab/common/deprecation.py @@ -34,7 +34,7 @@ else: import importlib_metadata -def get_real__name__(some_callable: Callable) -> str: +def _unstack_all_deprecation_decorators(function): """ This is another super edge magic case which is needed because we uses lazy_wraps because of logilab.common.modutils.LazyObject and because @@ -44,12 +44,18 @@ def get_real__name__(some_callable: Callable) -> str: Therefor, to get the real callable name when several lazy_wrapped decorator are used we need to travers the __wrapped__ attributes chain. """ + while hasattr(function, "__wrapped__"): + function = function.__wrapped__ + + return function + + +def get_real__name__(some_callable: Callable) -> str: + return _unstack_all_deprecation_decorators(some_callable).__name__ - targeted_callable = some_callable - while hasattr(targeted_callable, "__wrapped__"): - targeted_callable = targeted_callable.__wrapped__ # type: ignore - return targeted_callable.__name__ +def get_real__module__(some_callable: Callable) -> str: + return _unstack_all_deprecation_decorators(some_callable).__module__ def lazy_wraps(wrapped: Callable) -> Callable: @@ -163,12 +169,22 @@ def _get_package_name(python_object) -> Optional[str]: # instantiate abstract class 'Distribution' with abstract attributes # 'locate_file' and 'read_text' for distribution in importlib_metadata.Distribution().discover(): # type: ignore - if distribution.files and hasattr(distribution, "name"): + if distribution.files: for file in distribution.files: - _cached_path_to_package[str(distribution.locate_file(file))] = distribution.name + # sometime distribution has a "name" attribute, sometime not + if hasattr(distribution, "name"): + _cached_path_to_package[ + str(distribution.locate_file(file)) + ] = distribution.name + elif "name" in distribution.metadata: + _cached_path_to_package[ + str(distribution.locate_file(file)) + ] = distribution.metadata["name"] try: - return _cached_path_to_package.get(inspect.getfile(python_object)) + return _cached_path_to_package.get( + inspect.getfile(_unstack_all_deprecation_decorators(python_object)) + ) except TypeError: return None @@ -320,7 +336,7 @@ def callable_renamed( }, stacklevel=3, version=version, - module_name=new_function.__module__, + module_name=get_real__module__(new_function), ) return new_function(*args, **kwargs) @@ -361,7 +377,7 @@ def argument_removed(old_argument_name: str, version: Optional[str] = None) -> C }, stacklevel=3, version=version, - module_name=func.__module__, + module_name=get_real__module__(func), ) del kwargs[old_argument_name] @@ -398,7 +414,7 @@ def callable_deprecated( }, version=version, stacklevel=stacklevel + 1, - module_name=func.__module__, + module_name=get_real__module__(func), ) return func(*args, **kwargs) @@ -425,7 +441,7 @@ def _generate_class_deprecated(): def __call__(cls, *args, **kwargs): message = getattr(cls, "__deprecation_warning__", "%(cls)s is deprecated") % { - "cls": cls.__name__ + "cls": get_real__name__(cls) } send_warning( message, @@ -480,8 +496,8 @@ def attribute_renamed(old_name: str, new_name: str, version: Optional[str] = Non def _class_wrap(klass: type) -> type: reason = ( - f"{klass.__name__}.{old_name} has been renamed and is deprecated, use " - f"{klass.__name__}.{new_name} instead" + f"{get_real__name__(klass)}.{old_name} has been renamed and is deprecated, use " + f"{get_real__name__(klass)}.{new_name} instead" ) def _get_old(self) -> Any: @@ -497,7 +513,7 @@ def attribute_renamed(old_name: str, new_name: str, version: Optional[str] = Non }, stacklevel=3, version=version, - module_name=klass.__module__, + module_name=get_real__module__(klass), ) return getattr(self, new_name) @@ -514,7 +530,7 @@ def attribute_renamed(old_name: str, new_name: str, version: Optional[str] = Non }, stacklevel=3, version=version, - module_name=klass.__module__, + module_name=get_real__module__(klass), ) setattr(self, new_name, value) @@ -531,7 +547,7 @@ def attribute_renamed(old_name: str, new_name: str, version: Optional[str] = Non }, stacklevel=3, version=version, - module_name=klass.__module__, + module_name=get_real__module__(klass), ) delattr(self, new_name) @@ -580,7 +596,7 @@ def argument_renamed(old_name: str, new_name: str, version: Optional[str] = None }, stacklevel=3, version=version, - module_name=func.__module__, + module_name=get_real__module__(func), ) kwargs[new_name] = kwargs[old_name] del kwargs[old_name] @@ -674,7 +690,7 @@ def class_renamed( """ class_dict: Dict[str, Any] = {} 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, get_real__name__(new_class)) class_dict["__deprecation_warning__"] = message class_dict["__deprecation_warning_class__"] = deprecated_warning_class @@ -682,7 +698,7 @@ def class_renamed( class_dict["__deprecation_warning_class_kwargs__"] = { "kind": DeprecationWarningKind.CLASS, "old_name": old_name, - "new_name": new_class.__name__, + "new_name": get_real__name__(new_class), "version": version, "package": _get_package_name(new_class), } @@ -705,7 +721,7 @@ def class_renamed( def __init__(self, *args, **kwargs): msg = class_dict.get( "__deprecation_warning__", - f"{old_name} is deprecated, use {new_class.__name__} instead", + f"{old_name} is deprecated, use {get_real__name__(new_class)} instead", ) send_warning( msg, @@ -713,7 +729,7 @@ def class_renamed( deprecation_class_kwargs={ "kind": DeprecationWarningKind.CLASS, "old_name": old_name, - "new_name": new_class.__name__, + "new_name": get_real__name__(new_class), "version": version, "package": _get_package_name(new_class), }, @@ -735,7 +751,7 @@ def class_moved( another module """ if old_name is None: - old_name = new_class.__name__ + old_name = get_real__name__(new_class) old_module = _get_module_name(1) @@ -743,8 +759,8 @@ def class_moved( message = "class %s.%s is now available as %s.%s" % ( old_module, old_name, - new_class.__module__, - new_class.__name__, + get_real__module__(new_class), + get_real__name__(new_class), ) module_name = _get_module_name(1) @@ -759,9 +775,9 @@ def class_moved( deprecated_warning_kwargs={ "kind": DeprecationWarningKind.CLASS, "old_module": old_module, - "new_module": new_class.__module__, + "new_module": get_real__module__(new_class), "old_name": old_name, - "new_name": new_class.__name__, + "new_name": get_real__name__(new_class), "version": version, "package": _get_package_name(new_class), },