From: Mike Bayer Date: Wed, 20 Feb 2013 23:24:46 +0000 (-0500) Subject: - Added new helper function :func:`.was_deleted`, returns True X-Git-Tag: rel_0_8_0~18^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26fb4b81638189547dd24f525ad0d146f2646916;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Added new helper function :func:`.was_deleted`, returns True if the given object was the subject of a :meth:`.Session.delete` operation. - An object that's deleted from a session will be de-associated with that session fully after the transaction is committed, that is the :func:`.object_session` function will return None. [ticket:2658] --- diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index 296141c799..8951217ffb 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -6,6 +6,22 @@ .. changelog:: :version: 0.8.0 + .. change:: + :tags: feature, orm + :tickets: 2658 + + Added new helper function :func:`.was_deleted`, returns True + if the given object was the subject of a :meth:`.Session.delete` + operation. + + .. change:: + :tags: bug, orm + :tickets: 2658 + + An object that's deleted from a session will be de-associated with + that session fully after the transaction is committed, that is + the :func:`.object_session` function will return None. + .. change:: :tags: bug, oracle diff --git a/doc/build/orm/session.rst b/doc/build/orm/session.rst index 00d67b512b..97d6f15a0e 100644 --- a/doc/build/orm/session.rst +++ b/doc/build/orm/session.rst @@ -1946,6 +1946,8 @@ Session Utilites .. autofunction:: object_session +.. autofunction:: was_deleted + Attribute and State Management Utilities ----------------------------------------- diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index e9dde3ca78..0132bb3897 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -35,6 +35,7 @@ from .util import ( object_mapper, outerjoin, polymorphic_union, + was_deleted, with_parent, with_polymorphic, ) @@ -125,6 +126,7 @@ __all__ = ( 'undefer', 'undefer_group', 'validates', + 'was_deleted', 'with_polymorphic' ) diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 00c6d4227f..2915fd4c8c 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -255,6 +255,10 @@ class SessionTransaction(object): if not self.nested and self.session.expire_on_commit: for s in self.session.identity_map.all_states(): s._expire(s.dict, self.session.identity_map._modified) + for s in self._deleted: + s.session_id = None + self._deleted.clear() + def _connection_for_bind(self, bind): self._assert_is_active() diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 492523e637..cc9dd6ba5c 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -1210,9 +1210,30 @@ def _orm_columns(entity): def has_identity(object): + """Return True if the given object has a database + identity. + + This typically corresponds to the object being + in either the persistent or detached state. + + .. seealso:: + + :func:`.was_deleted` + + """ state = attributes.instance_state(object) return state.has_identity +def was_deleted(object): + """Return True if the given object was deleted + within a session flush. + + .. versionadded:: 0.8.0 + + """ + + state = attributes.instance_state(object) + return state.deleted def instance_str(instance): """Return a string describing an instance.""" diff --git a/test/orm/test_session.py b/test/orm/test_session.py index ff4091ebe6..0a50a48cb1 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -12,7 +12,7 @@ from sqlalchemy import testing from sqlalchemy import Integer, String, Sequence from sqlalchemy.testing.schema import Table, Column from sqlalchemy.orm import mapper, relationship, backref, joinedload, \ - exc as orm_exc, object_session + exc as orm_exc, object_session, was_deleted from sqlalchemy.util import pypy from sqlalchemy.testing import fixtures from test.orm import _fixtures @@ -835,6 +835,24 @@ class SessionStateWFixtureTest(_fixtures.FixtureTest): assert sa.orm.object_session(a) is None assert sa.orm.attributes.instance_state(a).session_id is None + def test_deleted_expunged(self): + users, User = self.tables.users, self.classes.User + + mapper(User, users) + sess = Session() + + u1 = sess.query(User).first() + sess.delete(u1) + + assert not was_deleted(u1) + sess.flush() + + assert was_deleted(u1) + assert u1 not in sess + assert object_session(u1) is sess + sess.commit() + + assert object_session(u1) is None class WeakIdentityMapTest(_fixtures.FixtureTest):