--- /dev/null
+.. change::
+ :tags: bug, orm
+ :tickets: 4067
+ :versions: 1.2.0b3
+
+ An :class:`.InvalidRequestError` is raised when a :func:`.synonym`
+ is used against an attribute that is not against a :class:`.MapperProperty`,
+ such as an association proxy. Previously, a recursion overflow would
+ occur trying to locate non-existent attributes.
@util.memoized_property
def _proxied_property(self):
- return getattr(self.parent.class_, self.name).property
+ attr = getattr(self.parent.class_, self.name)
+ if not hasattr(attr, 'property') or not \
+ isinstance(attr.property, MapperProperty):
+ raise sa_exc.InvalidRequestError(
+ """synonym() attribute "%s.%s" only supports """
+ """ORM mapped attributes, got %r""" % (
+ self.parent.class_.__name__,
+ self.name,
+ attr
+ )
+ )
+ return attr.property
def _comparator_factory(self, mapper):
prop = self._proxied_property
u = s.query(User).filter(User.y == 8).one()
eq_(u.y, 8)
+ def test_synonym_of_non_property_raises(self):
+ from sqlalchemy.ext.associationproxy import association_proxy
+
+ class User(object):
+ pass
+
+ users, Address, addresses = (
+ self.tables.users,
+ self.classes.Address,
+ self.tables.addresses)
+
+ mapper(User, users, properties={
+ 'y': synonym('x'),
+ 'addresses': relationship(Address)
+ })
+ mapper(Address, addresses)
+ User.x = association_proxy("addresses", "email_address")
+
+ assert_raises_message(
+ sa.exc.InvalidRequestError,
+ r'synonym\(\) attribute "User.x" only supports ORM mapped '
+ 'attributes, got .*AssociationProxy',
+ getattr, User.y, "property"
+ )
+
def test_synonym_column_location(self):
users, User = self.tables.users, self.classes.User