summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/state.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-04 18:32:38 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-04 18:32:38 -0400
commite07f4b9837455971ce95a1f306dc80a3f716ed64 (patch)
treed992c22193dc99526fa82c3a2024579690ca3724 /lib/sqlalchemy/orm/state.py
parent79f26dbff98a3e5625c94fbea5bfb35a2d7016cf (diff)
downloadsqlalchemy-e07f4b9837455971ce95a1f306dc80a3f716ed64.tar.gz
- [feature] A warning is emitted when a reference
to an instrumented collection is no longer associated with the parent class due to expiration/attribute refresh/collection replacement, but an append or remove operation is received on the now-detached collection. [ticket:2476]
Diffstat (limited to 'lib/sqlalchemy/orm/state.py')
-rw-r--r--lib/sqlalchemy/orm/state.py18
1 files changed, 14 insertions, 4 deletions
diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py
index 1c7fc2c41..9d17fa344 100644
--- a/lib/sqlalchemy/orm/state.py
+++ b/lib/sqlalchemy/orm/state.py
@@ -288,7 +288,9 @@ class InstanceState(interfaces._InspectionAttr):
"""Remove the given attribute and any
callables associated with it."""
- dict_.pop(key, None)
+ old = dict_.pop(key, None)
+ if old is not None and self.manager[key].impl.collection:
+ self.manager[key].impl._invalidate_collection(old)
self.callables.pop(key, None)
def _expire_attribute_pre_commit(self, dict_, key):
@@ -296,6 +298,8 @@ class InstanceState(interfaces._InspectionAttr):
The additional bookkeeping is finished up in commit_all().
+ Should only be called for scalar attributes.
+
This method is actually called a lot with joined-table
loading, when the second table isn't present in the result.
@@ -307,7 +311,9 @@ class InstanceState(interfaces._InspectionAttr):
"""Remove the given attribute and set the given callable
as a loader."""
- dict_.pop(key, None)
+ old = dict_.pop(key, None)
+ if old is not None and self.manager[key].impl.collection:
+ self.manager[key].impl._invalidate_collection(old)
self.callables[key] = callable_
def _expire(self, dict_, modified_set):
@@ -331,7 +337,9 @@ class InstanceState(interfaces._InspectionAttr):
if impl.accepts_scalar_loader and \
(impl.expire_missing or key in dict_):
self.callables[key] = self
- dict_.pop(key, None)
+ old = dict_.pop(key, None)
+ if impl.collection and old is not None:
+ impl._invalidate_collection(old)
self.manager.dispatch.expire(self, None)
@@ -342,7 +350,9 @@ class InstanceState(interfaces._InspectionAttr):
impl = self.manager[key].impl
if impl.accepts_scalar_loader:
self.callables[key] = self
- dict_.pop(key, None)
+ old = dict_.pop(key, None)
+ if impl.collection and old is not None:
+ impl._invalidate_collection(old)
self.committed_state.pop(key, None)
if pending: