summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-06-14 22:44:59 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-06-14 22:44:59 -0400
commit79d07c9abc7d4d3abb6bf2ca5ca66e87d3a11f08 (patch)
treef893aeac44103cae9fb5e21e99c7954043a64bb4
parentde08740d7c21fa9dcef453bfd07a3defa428e88f (diff)
downloadsqlalchemy-79d07c9abc7d4d3abb6bf2ca5ca66e87d3a11f08.tar.gz
Consult is_attrbute flag to determine descriptor; enable for assoc proxy
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
-rw-r--r--doc/build/changelog/unreleased_13/4729.rst10
-rw-r--r--lib/sqlalchemy/ext/associationproxy.py2
-rw-r--r--lib/sqlalchemy/orm/instrumentation.py5
-rw-r--r--test/ext/declarative/test_basic.py9
-rw-r--r--test/orm/test_inspect.py7
5 files changed, 30 insertions, 3 deletions
diff --git a/doc/build/changelog/unreleased_13/4729.rst b/doc/build/changelog/unreleased_13/4729.rst
new file mode 100644
index 000000000..3fa55b667
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4729.rst
@@ -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.
diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py
index 9a8294f3c..32dee79c6 100644
--- a/lib/sqlalchemy/ext/associationproxy.py
+++ b/lib/sqlalchemy/ext/associationproxy.py
@@ -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__(
diff --git a/lib/sqlalchemy/orm/instrumentation.py b/lib/sqlalchemy/orm/instrumentation.py
index 7cf46227f..ee0cc0600 100644
--- a/lib/sqlalchemy/orm/instrumentation.py
+++ b/lib/sqlalchemy/orm/instrumentation.py
@@ -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):
diff --git a/test/ext/declarative/test_basic.py b/test/ext/declarative/test_basic.py
index b6c911813..935e6f431 100644
--- a/test/ext/declarative/test_basic.py
+++ b/test/ext/declarative/test_basic.py
@@ -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(
diff --git a/test/orm/test_inspect.py b/test/orm/test_inspect.py
index 48d69b6ed..e99d46672 100644
--- a/test/orm/test_inspect.py
+++ b/test/orm/test_inspect.py
@@ -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_
@@ -402,9 +403,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