diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2017-10-23 20:56:06 -0400 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@ci.zzzcomputing.com> | 2017-10-23 20:56:06 -0400 |
| commit | da4b0a41e1f3ce7530fe25137aa3d7ed77f3171e (patch) | |
| tree | 525643fb70921b757ae34463ebf9f471e3c18c7a | |
| parent | 7482ba0b3cf467aeaa87218020a357ad18325df8 (diff) | |
| parent | f14a58dea4b825beb4baaef44389880927543cc4 (diff) | |
| download | sqlalchemy-da4b0a41e1f3ce7530fe25137aa3d7ed77f3171e.tar.gz | |
Merge "Resolve AliasedClass when determining owning class of association proxy"
| -rw-r--r-- | doc/build/changelog/unreleased_11/4116.rst | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/associationproxy.py | 13 | ||||
| -rw-r--r-- | test/ext/test_associationproxy.py | 26 |
3 files changed, 47 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_11/4116.rst b/doc/build/changelog/unreleased_11/4116.rst new file mode 100644 index 000000000..f4cf1f47c --- /dev/null +++ b/doc/build/changelog/unreleased_11/4116.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, orm, ext + :tickets: 4116 + :versions: 1.2.0b4 + + Fixed bug where the association proxy would inadvertently link itself + to an :class:`.AliasedClass` object if it were called first with + the :class:`.AliasedClass` as a parent, causing errors upon subsequent + usage.
\ No newline at end of file diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py index 16a4f3540..c0dbb538e 100644 --- a/lib/sqlalchemy/ext/associationproxy.py +++ b/lib/sqlalchemy/ext/associationproxy.py @@ -19,6 +19,7 @@ import weakref from .. import exc, orm, util from ..orm import collections, interfaces from ..sql import not_, or_ +from .. import inspect def association_proxy(target_collection, attr, **kw): @@ -245,7 +246,17 @@ class AssociationProxy(interfaces.InspectionAttrInfo): def __get__(self, obj, class_): if self.owning_class is None: - self.owning_class = class_ and class_ or type(obj) + try: + insp = inspect(class_) + except exc.NoInspectionAvailable: + pass + else: + if hasattr(insp, 'mapper'): + self.owning_class = insp.mapper.class_ + + if self.owning_class is None: + self.owning_class = type(obj) + if obj is None: return self diff --git a/test/ext/test_associationproxy.py b/test/ext/test_associationproxy.py index 4653fdf83..28eb7a712 100644 --- a/test/ext/test_associationproxy.py +++ b/test/ext/test_associationproxy.py @@ -14,6 +14,7 @@ from sqlalchemy import testing from sqlalchemy.testing.schema import Table, Column from sqlalchemy.testing.mock import Mock, call from sqlalchemy.testing.assertions import expect_warnings +from sqlalchemy.ext.declarative import declarative_base class DictCollection(dict): @@ -1847,6 +1848,31 @@ class DictOfTupleUpdateTest(fixtures.TestBase): ) +class AttributeAccessTest(fixtures.TestBase): + def test_resolve_aliased_class(self): + Base = declarative_base() + + class A(Base): + __tablename__ = 'a' + id = Column(Integer, primary_key=True) + value = Column(String) + + class B(Base): + __tablename__ = 'b' + id = Column(Integer, primary_key=True) + a_id = Column(Integer, ForeignKey(A.id)) + a = relationship(A) + a_value = association_proxy('a', 'value') + + spec = aliased(B).a_value + + is_(spec.owning_class, B) + + spec = B.a_value + + is_(spec.owning_class, B) + + class InfoTest(fixtures.TestBase): def test_constructor(self): assoc = association_proxy('a', 'b', info={'some_assoc': 'some_value'}) |
