]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Consult is_attrbute flag to determine descriptor; enable for assoc proxy
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 15 Jun 2019 02:44:59 +0000 (22:44 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 15 Jun 2019 02:47:01 +0000 (22:47 -0400)
Fixed bug where the :attr:`.Mapper.all_orm_descriptors` accessor would
return an entry for the :class:`.Mapper` itself under the declarative
``__mapper___`` key, when this is not a descriptor.  The ``.is_attribute``
flag that's present on all :class:`.InspectionAttr` objects is now
consulted, which has also been modified to be ``True`` for an association
proxy, as it was erroneously set to False for this object.

Fixes: #4729
Change-Id: Ia02388cc25d004e32d337140b62a587f3e5a0b7b
(cherry picked from commit 79d07c9abc7d4d3abb6bf2ca5ca66e87d3a11f08)

doc/build/changelog/unreleased_13/4729.rst [new file with mode: 0644]
lib/sqlalchemy/ext/associationproxy.py
lib/sqlalchemy/orm/instrumentation.py
test/ext/declarative/test_basic.py
test/orm/test_inspect.py

diff --git a/doc/build/changelog/unreleased_13/4729.rst b/doc/build/changelog/unreleased_13/4729.rst
new file mode 100644 (file)
index 0000000..3fa55b6
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 4729
+
+    Fixed bug where the :attr:`.Mapper.all_orm_descriptors` accessor would
+    return an entry for the :class:`.Mapper` itself under the declarative
+    ``__mapper___`` key, when this is not a descriptor.  The ``.is_attribute``
+    flag that's present on all :class:`.InspectionAttr` objects is now
+    consulted, which has also been modified to be ``True`` for an association
+    proxy, as it was erroneously set to False for this object.
index 9a8294f3c776ff4116186320a505de182ed242da..32dee79c6926173caa690d5526c6ed7ec9f430a8 100644 (file)
@@ -93,7 +93,7 @@ ASSOCIATION_PROXY = util.symbol("ASSOCIATION_PROXY")
 class AssociationProxy(interfaces.InspectionAttrInfo):
     """A descriptor that presents a read/write view of an object attribute."""
 
-    is_attribute = False
+    is_attribute = True
     extension_type = ASSOCIATION_PROXY
 
     def __init__(
index 7cf46227f8839fc939cb226d9594c388a56032c3..ee0cc06006c715b48228579de0c5af03fff06eb1 100644 (file)
@@ -143,7 +143,10 @@ class ClassManager(dict):
             for key in set(supercls.__dict__).difference(exclude):
                 exclude.add(key)
                 val = supercls.__dict__[key]
-                if isinstance(val, interfaces.InspectionAttr):
+                if (
+                    isinstance(val, interfaces.InspectionAttr)
+                    and val.is_attribute
+                ):
                     yield key, val
 
     def _get_class_attr_mro(self, key, default=None):
index 3fe2f1bfe97e8f20ee25f0a2e398fc97cdc2ddb7..264c4839c9cb0168e7dd49edf2d203ae832cc1ed 100644 (file)
@@ -1337,6 +1337,15 @@ class DeclarativeTest(DeclarativeTestBase):
 
         eq_(Foo.__mapper__.CHECK, True)
 
+    def test_no_change_to_all_descriptors(self):
+        base = decl.declarative_base()
+
+        class Foo(base):
+            __tablename__ = "foo"
+            id = Column(Integer, primary_key=True)
+
+        eq_(Foo.__mapper__.all_orm_descriptors.keys(), ["id"])
+
     def test_oops(self):
 
         with testing.expect_warnings(
index 368199b96fab41d950202b4e9771df0507ba06f5..4a39fc87d0af7047f32b24852a74be4bd61238b4 100644 (file)
@@ -11,6 +11,7 @@ from sqlalchemy.orm import Session
 from sqlalchemy.orm import synonym
 from sqlalchemy.orm.attributes import instance_state
 from sqlalchemy.orm.attributes import NO_VALUE
+from sqlalchemy.orm.base import InspectionAttr
 from sqlalchemy.orm.util import identity_key
 from sqlalchemy.testing import assert_raises_message
 from sqlalchemy.testing import eq_
@@ -400,9 +401,13 @@ class TestORMInspection(_fixtures.FixtureTest):
         assert "name" in u1.__dict__
 
     def test_attrs_props_prop_added_after_configure(self):
-        class AnonClass(object):
+        class Thing(InspectionAttr):
             pass
 
+        class AnonClass(object):
+            __foo__ = "bar"
+            __bat__ = Thing()
+
         from sqlalchemy.orm import mapper, column_property
         from sqlalchemy.ext.hybrid import hybrid_property