diff options
author | Laurent Peuch <cortex@worlddomination.be> | 2020-05-22 16:51:56 +0200 |
---|---|---|
committer | Laurent Peuch <cortex@worlddomination.be> | 2020-05-22 16:51:56 +0200 |
commit | fcc526e63d7c1333845dd7ebba97db646aba7bcd (patch) | |
tree | 9ddc531dc4bd6a4feed694b8c65a7d1000042c29 | |
parent | 787bd229345479c9e193f2695366ff584157548e (diff) | |
download | logilab-common-fcc526e63d7c1333845dd7ebba97db646aba7bcd.tar.gz |
[deprecation/fix] rollback to old class_deprecation being a class behavior
It breaks CW because CW was using class_deprecated in a isinstance to select
the good views to uses.
-rw-r--r-- | logilab/common/deprecation.py | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py index 8b8f8a5..0ddedf2 100644 --- a/logilab/common/deprecation.py +++ b/logilab/common/deprecation.py @@ -23,7 +23,7 @@ import os import sys from warnings import warn from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES -from typing import Any, Callable, Dict, Optional, Iterable +from typing import Any, Callable, Dict, Optional from typing_extensions import Protocol @@ -237,25 +237,28 @@ deprecated: CallableDeprecatedCallable = callable_renamed( ) -def class_deprecated(old_name: str, parent: Iterable[type], class_dict: Dict[str, Any]) -> type: - class DeprecatedClass(*parent): # type: ignore - def __init__(self, *args, **kwargs): - msg: str = class_dict.get( - "__deprecation_warning__", f"{old_name} is deprecated" - ) # type: ignore +def _generate_class_deprecated(): + class _class_deprecated(type): + """metaclass to print a warning on instantiation of a deprecated class""" + + def __call__(cls, *args, **kwargs): + message = getattr(cls, "__deprecation_warning__", "%(cls)s is deprecated") % { + "cls": cls.__name__ + } send_warning( - msg, - stacklevel=class_dict.get("__deprecation_warning_stacklevel__", 3), - version=class_dict.get("__deprecation_warning_version__", None), - module_name=class_dict.get( - "__deprecation_warning_module_name__", _get_module_name(1) + message, + module_name=getattr( + cls, "__deprecation_warning_module_name__", _get_module_name(1) ), + stacklevel=getattr(cls, "__deprecation_warning_stacklevel__", 4), + version=getattr(cls, "__deprecation_warning_version__", None), ) - super(DeprecatedClass, self).__init__(*args, **kwargs) + return type.__call__(cls, *args, **kwargs) + + return _class_deprecated - DeprecatedClass.__name__ = old_name - return DeprecatedClass +class_deprecated = _generate_class_deprecated() def attribute_renamed(old_name: str, new_name: str, version: Optional[str] = None) -> Callable: @@ -412,7 +415,25 @@ def class_renamed( else: class_dict["__deprecation_warning_module_name__"] = _get_module_name(1) - return class_deprecated(old_name, (new_class,), class_dict) + try: + return class_deprecated(old_name, (new_class,), class_dict) + except (NameError, TypeError): + # in case of conflicting metaclass situation + # mypy can't handle dynamic base classes https://github.com/python/mypy/issues/2477 + class DeprecatedClass(new_class): # type: ignore + def __init__(self, *args, **kwargs): + msg = class_dict.get( + "__deprecation_warning__", + f"{old_name} is deprecated, use {new_class.__name__} instead", + ) + send_warning( + msg, + stacklevel=class_dict.get("__deprecation_warning_stacklevel__", 3), + version=class_dict.get("__deprecation_warning_version__", None), + ) + super(DeprecatedClass, self).__init__(*args, **kwargs) + + return DeprecatedClass def class_moved( |