From: Mike Bayer Date: Tue, 5 Mar 2019 18:28:54 +0000 (-0500) Subject: Ensure association proxy works over synonym X-Git-Tag: rel_1_3_1~6^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b78f4604658dc875221bda5a23423cb34742e428;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Ensure association proxy works over synonym Fixed regression where an association proxy linked to a synonym would no longer work, both at instance level and at class level. Fixes: #4522 Change-Id: I949079229ef87c12736c362df35444f6e30c8038 --- diff --git a/doc/build/changelog/unreleased_13/4522.rst b/doc/build/changelog/unreleased_13/4522.rst new file mode 100644 index 0000000000..cd0729600d --- /dev/null +++ b/doc/build/changelog/unreleased_13/4522.rst @@ -0,0 +1,6 @@ +.. change:: + :tags: bug, orm, ext + :tickets: 4522 + + Fixed regression where an association proxy linked to a synonym would no + longer work, both at instance level and at class level. diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py index a0ddf3a8b6..28b3bc5db3 100644 --- a/lib/sqlalchemy/orm/descriptor_props.py +++ b/lib/sqlalchemy/orm/descriptor_props.py @@ -39,6 +39,10 @@ class DescriptorProperty(MapperProperty): expire_missing = True collection = False + @property + def uses_objects(self): + return getattr(mapper.class_, prop.name).impl.uses_objects + def __init__(self, key): self.key = key diff --git a/test/ext/test_associationproxy.py b/test/ext/test_associationproxy.py index 4b07a383d1..6f701416cc 100644 --- a/test/ext/test_associationproxy.py +++ b/test/ext/test_associationproxy.py @@ -3089,6 +3089,58 @@ class MultiOwnerTest( self._assert_raises_ambiguous(lambda: D.c_data.any(B.id == 5)) +class ProxyOfSynonymTest(AssertsCompiledSQL, fixtures.DeclarativeMappedTest): + __dialect__ = "default" + + run_create_tables = None + + @classmethod + def setup_classes(cls): + from sqlalchemy.orm import synonym + + Base = cls.DeclarativeBasic + + class A(Base): + __tablename__ = "a" + + id = Column(Integer, primary_key=True) + data = Column(String) + bs = relationship("B", backref="a") + data_syn = synonym("data") + + b_data = association_proxy("bs", "data_syn") + + class B(Base): + __tablename__ = "b" + id = Column(Integer, primary_key=True) + a_id = Column(ForeignKey("a.id")) + data = Column(String) + data_syn = synonym("data") + + a_data = association_proxy("a", "data_syn") + + def test_o2m_instance_getter(self): + A, B = self.classes("A", "B") + + a1 = A(bs=[B(data="bdata1"), B(data="bdata2")]) + eq_(a1.b_data, ["bdata1", "bdata2"]) + + def test_m2o_instance_getter(self): + A, B = self.classes("A", "B") + + b1 = B(a=A(data="adata")) + eq_(b1.a_data, "adata") + + def test_o2m_expr(self): + A, B = self.classes("A", "B") + + self.assert_compile( + A.b_data == "foo", + "EXISTS (SELECT 1 FROM a, b WHERE a.id = b.a_id " + "AND b.data = :data_1)", + ) + + class ProxyAttrTest(fixtures.DeclarativeMappedTest): @classmethod def setup_classes(cls):