summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Peuch <cortex@worlddomination.be>2020-05-07 22:22:42 +0200
committerLaurent Peuch <cortex@worlddomination.be>2020-05-07 22:22:42 +0200
commit30d47f2bd6c3fb00108a7f2faebade1a30836fef (patch)
tree700d58e2ee31e3cca28ba69789f9625230d7ba8b
parent15578b2aa05c3121c64326db33081dc1ac368905 (diff)
downloadlogilab-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.py23
-rw-r--r--test/test_deprecation.py11
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