diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-16 08:56:17 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-16 11:29:53 -0400 |
| commit | b73fc8f874da94c9c5b2d94feb6b1b45b7f4f02b (patch) | |
| tree | a008891963604495c33205f3fcc0f92aba623592 /lib/sqlalchemy | |
| parent | b3d764fa768756cd7aef73253ccceac456c76c81 (diff) | |
| download | sqlalchemy-b73fc8f874da94c9c5b2d94feb6b1b45b7f4f02b.tar.gz | |
synonym fixes and enhancements
Fixed regression where an attribute that is mapped to a
:func:`_orm.synonym` could not be used in column loader options such as
:func:`_orm.load_only`.
Established support for :func:`_orm.synonym` in conjunction with hybrid
property, associationproxy, including that synonyms can be established
linking to these constructs which work fully. This is a behavior that was
semi-explicitly disallowed previously, however since it did not fail in
every scenario, explicit support for assoc proxy and hybrids has been
added.
Fixes: #6272
Fixes: #6267
Change-Id: Ie75bb3b535feeb6ccf3f6a391f21b69f241e625e
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/descriptor_props.py | 25 |
2 files changed, 20 insertions, 7 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index d1ed17f1a..9e326db64 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -487,6 +487,8 @@ def create_proxied_attribute(descriptor): """ + _extra_criteria = () + def __init__( self, class_, diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py index c30672566..f8c42ee60 100644 --- a/lib/sqlalchemy/orm/descriptor_props.py +++ b/lib/sqlalchemy/orm/descriptor_props.py @@ -22,6 +22,7 @@ from .. import schema from .. import sql from .. import util from ..sql import expression +from ..sql import operators class DescriptorProperty(MapperProperty): @@ -665,15 +666,22 @@ class SynonymProperty(DescriptorProperty): def uses_objects(self): return getattr(self.parent.class_, self.name).impl.uses_objects - # TODO: when initialized, check _proxied_property, + # TODO: when initialized, check _proxied_object, # emit a warning if its not a column-based property @util.memoized_property - def _proxied_property(self): + def _proxied_object(self): attr = getattr(self.parent.class_, self.name) if not hasattr(attr, "property") or not isinstance( attr.property, MapperProperty ): + # attribute is a non-MapperProprerty proxy such as + # hybrid or association proxy + if isinstance(attr, attributes.QueryableAttribute): + return attr.comparator + elif isinstance(attr, operators.ColumnOperators): + return attr + raise sa_exc.InvalidRequestError( """synonym() attribute "%s.%s" only supports """ """ORM mapped attributes, got %r""" @@ -682,13 +690,16 @@ class SynonymProperty(DescriptorProperty): return attr.property def _comparator_factory(self, mapper): - prop = self._proxied_property + prop = self._proxied_object - if self.comparator_factory: - comp = self.comparator_factory(prop, mapper) + if isinstance(prop, MapperProperty): + if self.comparator_factory: + comp = self.comparator_factory(prop, mapper) + else: + comp = prop.comparator_factory(prop, mapper) + return comp else: - comp = prop.comparator_factory(prop, mapper) - return comp + return prop def get_history(self, *arg, **kw): attr = getattr(self.parent.class_, self.name) |
