summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/descriptor_props.py34
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py
index 65fe58e61..c30672566 100644
--- a/lib/sqlalchemy/orm/descriptor_props.py
+++ b/lib/sqlalchemy/orm/descriptor_props.py
@@ -167,6 +167,8 @@ class CompositeProperty(DescriptorProperty):
"""
self._setup_arguments_on_columns()
+ _COMPOSITE_FGET = object()
+
def _create_descriptor(self):
"""Create the Python descriptor that will serve as
the access point on instances of the mapped class.
@@ -194,7 +196,9 @@ class CompositeProperty(DescriptorProperty):
state.key is not None or not _none_set.issuperset(values)
):
dict_[self.key] = self.composite_class(*values)
- state.manager.dispatch.refresh(state, None, [self.key])
+ state.manager.dispatch.refresh(
+ state, self._COMPOSITE_FGET, [self.key]
+ )
return dict_.get(self.key, None)
@@ -268,16 +272,32 @@ class CompositeProperty(DescriptorProperty):
def _setup_event_handlers(self):
"""Establish events that populate/expire the composite attribute."""
- def load_handler(state, *args):
- _load_refresh_handler(state, args, is_refresh=False)
+ def load_handler(state, context):
+ _load_refresh_handler(state, context, None, is_refresh=False)
+
+ def refresh_handler(state, context, to_load):
+ # note this corresponds to sqlalchemy.ext.mutable load_attrs()
- def refresh_handler(state, *args):
- _load_refresh_handler(state, args, is_refresh=True)
+ if not to_load or (
+ {self.key}.union(self._attribute_keys)
+ ).intersection(to_load):
+ _load_refresh_handler(state, context, to_load, is_refresh=True)
- def _load_refresh_handler(state, args, is_refresh):
+ def _load_refresh_handler(state, context, to_load, is_refresh):
dict_ = state.dict
- if not is_refresh and self.key in dict_:
+ # if context indicates we are coming from the
+ # fget() handler, this already set the value; skip the
+ # handler here. (other handlers like mutablecomposite will still
+ # want to catch it)
+ # there's an insufficiency here in that the fget() handler
+ # really should not be using the refresh event and there should
+ # be some other event that mutablecomposite can subscribe
+ # towards for this.
+
+ if (
+ not is_refresh or context is self._COMPOSITE_FGET
+ ) and self.key in dict_:
return
# if column elements aren't loaded, skip.