]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
dont transfer __weakref__ to regenerated class
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 9 Jun 2022 13:53:43 +0000 (09:53 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 9 Jun 2022 13:54:04 +0000 (09:54 -0400)
Repaired a deprecation warning class decorator that was preventing key
objects such as :class:`_engine.Connection` from having a proper
``__weakref__`` attribute, causing operations like Python standard library
``inspect.getmembers()`` to fail.

Fixes: #8115
Change-Id: Ifd0bc2325fb9dc9e1431998c308b7fc081968373

doc/build/changelog/unreleased_14/8115.rst [new file with mode: 0644]
lib/sqlalchemy/util/deprecations.py
test/base/test_warnings.py

diff --git a/doc/build/changelog/unreleased_14/8115.rst b/doc/build/changelog/unreleased_14/8115.rst
new file mode 100644 (file)
index 0000000..856a76a
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, engine
+    :tickets: 8115
+
+    Repaired a deprecation warning class decorator that was preventing key
+    objects such as :class:`_engine.Connection` from having a proper
+    ``__weakref__`` attribute, causing operations like Python standard library
+    ``inspect.getmembers()`` to fail.
+
index 2ef51608b631724e09de18854f540d6d3cf4f79e..a7bba2cf81015ff964f336b006b27c50d80ae71c 100644 (file)
@@ -378,6 +378,7 @@ def _decorate_cls_with_warning(
             clsdict = dict(cls.__dict__)
             clsdict["__doc__"] = doc
             clsdict.pop("__dict__", None)
+            clsdict.pop("__weakref__", None)
             cls = type(cls.__name__, cls.__bases__, clsdict)  # type: ignore
             if constructor is not None:
                 constructor_fn = clsdict[constructor]
index e32c8f5ab523067e15b935ec15814337d25f035e..e951fcafcd9efd6e9138a2db2337777f5b09a3a4 100644 (file)
@@ -1,6 +1,9 @@
+from sqlalchemy import testing
+from sqlalchemy.exc import SADeprecationWarning
 from sqlalchemy.testing import eq_
 from sqlalchemy.testing import expect_deprecated
 from sqlalchemy.testing import fixtures
+from sqlalchemy.util.deprecations import _decorate_cls_with_warning
 from sqlalchemy.util.deprecations import warn_deprecated_limited
 from sqlalchemy.util.langhelpers import _hash_limit_string
 
@@ -34,3 +37,46 @@ class WarnDeprecatedLimitedTest(fixtures.TestBase):
 
         eq_(len(printouts), occurrences)
         eq_(len(messages), cap)
+
+
+class ClsWarningTest(fixtures.TestBase):
+    @testing.fixture
+    def dep_cls_fixture(self):
+        class Connectable(object):
+            """a docstring"""
+
+            some_member = "foo"
+
+        Connectable = _decorate_cls_with_warning(
+            Connectable,
+            None,
+            SADeprecationWarning,
+            "a message",
+            "2.0",
+            "another message",
+        )
+
+        return Connectable
+
+    def test_dep_inspectable(self, dep_cls_fixture):
+        """test #8115"""
+
+        import inspect
+
+        class PlainClass(object):
+            some_member = "bar"
+
+        pc_keys = dict(inspect.getmembers(PlainClass()))
+        insp_keys = dict(inspect.getmembers(dep_cls_fixture()))
+
+        assert set(insp_keys).intersection(
+            (
+                "__class__",
+                "__doc__",
+                "__eq__",
+                "__dict__",
+                "__weakref__",
+                "some_member",
+            )
+        )
+        eq_(set(pc_keys), set(insp_keys))