diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-07-19 21:33:58 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-07-19 21:33:58 +0000 |
commit | a4781e4d76c6b1bfb8ae5345c2e09ae35045d8e6 (patch) | |
tree | 6fd8340944b3ccae2dff328c7f64d0f0c2ac4e55 /lib/sqlalchemy/orm/dynamic.py | |
parent | d56862cbca1796edafab8845fd1852f6183512f8 (diff) | |
download | sqlalchemy-a4781e4d76c6b1bfb8ae5345c2e09ae35045d8e6.tar.gz |
- A critical fix to dynamic relations allows the
"modified" history to be properly cleared after
a flush().
Diffstat (limited to 'lib/sqlalchemy/orm/dynamic.py')
-rw-r--r-- | lib/sqlalchemy/orm/dynamic.py | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 424ef85b7..3d139dff1 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -18,7 +18,7 @@ from sqlalchemy.orm import ( attributes, object_session, util as mapperutil, strategies, ) from sqlalchemy.orm.query import Query -from sqlalchemy.orm.util import has_identity +from sqlalchemy.orm.util import _state_has_identity, has_identity class DynaLoader(strategies.AbstractRelationLoader): @@ -55,7 +55,8 @@ class DynamicAttributeImpl(attributes.AttributeImpl): return history.added_items + history.unchanged_items def fire_append_event(self, state, value, initiator): - state.modified = True + collection_history = self._modified_event(state) + collection_history.added_items.append(value) if self.trackparent and value is not None: self.sethasparent(attributes.instance_state(value), True) @@ -63,22 +64,36 @@ class DynamicAttributeImpl(attributes.AttributeImpl): ext.append(state, value, initiator or self) def fire_remove_event(self, state, value, initiator): - state.modified = True + collection_history = self._modified_event(state) + collection_history.deleted_items.append(value) if self.trackparent and value is not None: self.sethasparent(attributes.instance_state(value), False) for ext in self.extensions: ext.remove(state, value, initiator or self) + + def _modified_event(self, state): + state.modified = True + if self.key not in state.committed_state: + state.committed_state[self.key] = CollectionHistory(self, state) + + # this is a hack to allow the _base.ComparableEntity fixture + # to work + state.dict[self.key] = True + + return state.committed_state[self.key] def set(self, state, value, initiator): if initiator is self: return - - old_collection = self.get(state).assign(value) - - # TODO: emit events ??? - state.modified = True + + collection_history = self._modified_event(state) + if _state_has_identity(state): + old_collection = list(self.get(state)) + else: + old_collection = [] + collection_history.replace(old_collection, value) def delete(self, *args, **kwargs): raise NotImplementedError() @@ -88,11 +103,11 @@ class DynamicAttributeImpl(attributes.AttributeImpl): return (c.added_items, c.unchanged_items, c.deleted_items) def _get_collection_history(self, state, passive=False): - try: - c = state.dict[self.key] - except KeyError: - state.dict[self.key] = c = CollectionHistory(self, state) - + if self.key in state.committed_state: + c = state.committed_state[self.key] + else: + c = CollectionHistory(self, state) + if not passive: return CollectionHistory(self, state, apply_to=c) else: @@ -100,15 +115,13 @@ class DynamicAttributeImpl(attributes.AttributeImpl): def append(self, state, value, initiator, passive=False): if initiator is not self: - self._get_collection_history(state, passive=True).added_items.append(value) self.fire_append_event(state, value, initiator) def remove(self, state, value, initiator, passive=False): if initiator is not self: - self._get_collection_history(state, passive=True).deleted_items.append(value) self.fire_remove_event(state, value, initiator) - + class AppenderQuery(Query): def __init__(self, attr, state): super(AppenderQuery, self).__init__(attr.target_mapper, None) @@ -170,15 +183,6 @@ class AppenderQuery(Query): q = q.order_by(self.attr.order_by) return q - def assign(self, collection): - instance = self.instance - if has_identity(instance): - oldlist = list(self) - else: - oldlist = [] - self.attr._get_collection_history(attributes.instance_state(self.instance), passive=True).replace(oldlist, collection) - return oldlist - def append(self, item): self.attr.append(attributes.instance_state(self.instance), item, None) |