summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-08-26 11:32:50 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-08-26 11:32:50 -0400
commitaf9fd453c08aac4f4e45f6f6ba94da89b42afe54 (patch)
treef556b497cf61e44a6a8582f060d106685aa52e81 /lib/sqlalchemy/orm/session.py
parent506a0b103d7c4552679b711a4686a41a8842b10a (diff)
downloadsqlalchemy-af9fd453c08aac4f4e45f6f6ba94da89b42afe54.tar.gz
- An object that's been deleted now gets a flag
'deleted', which prohibits the object from being re-add()ed to the session, as previously the object would live in the identity map silently until its attributes were accessed. The make_transient() function now resets this flag along with the "key" flag. - make_transient() can be safely called on an already transient instance.
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py24
1 files changed, 19 insertions, 5 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 86d5dd773..06d5b89a1 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -278,8 +278,11 @@ class SessionTransaction(object):
for s in set(self._new).union(self.session._new):
self.session._expunge_state(s)
-
+
for s in set(self._deleted).union(self.session._deleted):
+ if s.deleted:
+ # assert s in self._deleted
+ del s.deleted
self.session._update_impl(s)
assert not self.session._deleted
@@ -1102,6 +1105,7 @@ class Session(object):
self.identity_map.discard(state)
self._deleted.pop(state, None)
+ state.deleted = True
def _save_without_cascade(self, instance):
"""Used by scoping.py to save on init without cascade."""
@@ -1309,7 +1313,13 @@ class Session(object):
raise sa_exc.InvalidRequestError(
"Instance '%s' is not persisted" %
mapperutil.state_str(state))
-
+
+ if state.deleted:
+ raise sa_exc.InvalidRequestError(
+ "Instance '%s' has been deleted. Use the make_transient() "
+ "function to send this object back to the transient state." %
+ mapperutil.state_str(state)
+ )
self._attach(state)
self._deleted.pop(state, None)
self.identity_map.add(state)
@@ -1655,7 +1665,9 @@ def make_transient(instance):
This will remove its association with any
session and additionally will remove its "identity key",
such that it's as though the object were newly constructed,
- except retaining its values.
+ except retaining its values. It also resets the
+ "deleted" flag on the state if this object
+ had been explicitly deleted by its session.
Attributes which were "expired" or deferred at the
instance level are reverted to undefined, and
@@ -1670,8 +1682,10 @@ def make_transient(instance):
# remove expired state and
# deferred callables
state.callables.clear()
- del state.key
-
+ if state.key:
+ del state.key
+ if state.deleted:
+ del state.deleted
def object_session(instance):
"""Return the ``Session`` to which instance belongs.