diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-06-14 22:44:59 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-06-14 22:44:59 -0400 |
commit | 79d07c9abc7d4d3abb6bf2ca5ca66e87d3a11f08 (patch) | |
tree | f893aeac44103cae9fb5e21e99c7954043a64bb4 | |
parent | de08740d7c21fa9dcef453bfd07a3defa428e88f (diff) | |
download | sqlalchemy-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.rst | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/ext/associationproxy.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/instrumentation.py | 5 | ||||
-rw-r--r-- | test/ext/declarative/test_basic.py | 9 | ||||
-rw-r--r-- | test/orm/test_inspect.py | 7 |
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 |