diff options
author | Laurent Peuch <cortex@worlddomination.be> | 2020-05-07 22:22:42 +0200 |
---|---|---|
committer | Laurent Peuch <cortex@worlddomination.be> | 2020-05-07 22:22:42 +0200 |
commit | 30d47f2bd6c3fb00108a7f2faebade1a30836fef (patch) | |
tree | 700d58e2ee31e3cca28ba69789f9625230d7ba8b | |
parent | 15578b2aa05c3121c64326db33081dc1ac368905 (diff) | |
download | logilab-common-30d47f2bd6c3fb00108a7f2faebade1a30836fef.tar.gz |
[fix] metaclass conflict for class_deprecated
Actually the old compatibility code actually prevented this bug so back it up.
-rw-r--r-- | logilab/common/deprecation.py | 23 | ||||
-rw-r--r-- | test/test_deprecation.py | 11 |
2 files changed, 33 insertions, 1 deletions
diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py index b5f40dd..a6f448f 100644 --- a/logilab/common/deprecation.py +++ b/logilab/common/deprecation.py @@ -177,7 +177,28 @@ def callable_deprecated(reason=None, version=None, stacklevel=2): deprecated = callable_renamed(old_name="deprecated", new_function=callable_deprecated) -class class_deprecated(type): +def class_deprecated(old_name, parents, class_dict): + try: + return _class_deprecated(old_name, parents, clsdict) + except (NameError, TypeError): + # in case of conflicting metaclass situation + class DeprecatedClass(*parents): + def __init__(self, *args, **kwargs): + msg = class_dict.get("__deprecation_warning__", f"{old_name} is deprecated") + 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) + ), + ) + super(DeprecatedClass, self).__init__(*args, **kwargs) + + return DeprecatedClass + + +class _class_deprecated(type): """metaclass to print a warning on instantiation of a deprecated class""" def __call__(cls, *args, **kwargs): diff --git a/test/test_deprecation.py b/test/test_deprecation.py index 78b2256..65ef8fd 100644 --- a/test/test_deprecation.py +++ b/test/test_deprecation.py @@ -63,6 +63,17 @@ class RawInputTC(TestCase): self.messages, ["[test_deprecation] OldClass is deprecated, use AnyClass instead"] ) + def test_class_renamed_conflict_metaclass(self): + class SomeMetaClass(type): + pass + + class AnyClass(metaclass=SomeMetaClass): + pass + + # make sure the "metaclass conflict: the metaclass of a derived class # must be a + # (non-strict) subclass of the metaclasses of all its bases" exception won't be raised + deprecation.class_renamed("OldClass", AnyClass) + def test_class_moved(self): class AnyClass(object): pass |