summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2017-10-23 20:56:06 -0400
committerGerrit Code Review <gerrit@ci.zzzcomputing.com>2017-10-23 20:56:06 -0400
commitda4b0a41e1f3ce7530fe25137aa3d7ed77f3171e (patch)
tree525643fb70921b757ae34463ebf9f471e3c18c7a
parent7482ba0b3cf467aeaa87218020a357ad18325df8 (diff)
parentf14a58dea4b825beb4baaef44389880927543cc4 (diff)
downloadsqlalchemy-da4b0a41e1f3ce7530fe25137aa3d7ed77f3171e.tar.gz
Merge "Resolve AliasedClass when determining owning class of association proxy"
-rw-r--r--doc/build/changelog/unreleased_11/4116.rst9
-rw-r--r--lib/sqlalchemy/ext/associationproxy.py13
-rw-r--r--test/ext/test_associationproxy.py26
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'})