From: Mike Bayer Date: Thu, 20 Sep 2012 22:39:27 +0000 (-0400) Subject: - [feature] New session events after_transaction_create X-Git-Tag: rel_0_8_0b1~150 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=248cf4c5d2f227c7cc49772f023807aebeb5c969;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [feature] New session events after_transaction_create and after_transaction_end allows tracking of new SessionTransaction objects. If the object is inspected, can be used to determine when a session first becomes active and when it deactivates. --- diff --git a/CHANGES b/CHANGES index 5ac1b4d347..f8991bd038 100644 --- a/CHANGES +++ b/CHANGES @@ -153,6 +153,13 @@ underneath "0.7.xx". PG's DELETE..USING is also not available in Core yet. + - [feature] New session events after_transaction_create + and after_transaction_end + allows tracking of new SessionTransaction objects. + If the object is inspected, can be used to determine + when a session first becomes active and when + it deactivates. + - [bug] Improvements to joined/subquery eager loading dealing with chains of subclass entities sharing a common base, with no specific "join depth" diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py index 67f6d64313..61517770f8 100644 --- a/lib/sqlalchemy/orm/events.py +++ b/lib/sqlalchemy/orm/events.py @@ -955,6 +955,26 @@ class SessionEvents(event.Events): def _remove(cls, identifier, target, fn): raise NotImplementedError("Removal of session events not yet implemented") + def after_transaction_create(self, session, transaction): + """Execute when a new :class:`.SessionTransaction` is created. + + :param session: the target :class:.`Session`. + :param transaction: the target :class:`.SessionTransaction`. + + .. versionadded:: 0.8 + + """ + + def after_transaction_end(self, session, transaction): + """Execute when the span of a :class:`.SessionTransaction` ends. + + :param session: the target :class:.`Session`. + :param transaction: the target :class:`.SessionTransaction`. + + .. versionadded:: 0.8 + + """ + def before_commit(self, session): """Execute before commit is called. diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index e0f79cd8a5..36ff5fc84e 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -150,6 +150,9 @@ class SessionTransaction(object): if self.session._enable_transaction_accounting: self._take_snapshot() + if self.session.dispatch.after_transaction_create: + self.session.dispatch.after_transaction_create(self.session, self) + @property def is_active(self): return self.session is not None and self._active @@ -379,9 +382,14 @@ class SessionTransaction(object): connection.close() else: transaction.close() + + self._deactivate() + if self.session.dispatch.after_transaction_end: + self.session.dispatch.after_transaction_end(self.session, self) + + if self._parent is None: if not self.session.autocommit: self.session.begin() - self._deactivate() self.session = None self._connections = None diff --git a/test/orm/test_events.py b/test/orm/test_events.py index bf413125ac..e49a4a6a7a 100644 --- a/test/orm/test_events.py +++ b/test/orm/test_events.py @@ -545,6 +545,8 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): sess = Session(**kw) for evt in [ + 'after_transaction_create', + 'after_transaction_end', 'before_commit', 'after_commit', 'after_rollback', @@ -576,9 +578,10 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): sess.flush() eq_( canary, - [ 'before_attach', 'after_attach', 'before_flush', 'after_begin', + [ 'before_attach', 'after_attach', 'before_flush', + 'after_transaction_create', 'after_begin', 'after_flush', 'after_flush_postexec', - 'before_commit', 'after_commit',] + 'before_commit', 'after_commit','after_transaction_end'] ) def test_rollback_hook(self): @@ -597,11 +600,17 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): sess.commit ) sess.rollback() - eq_(canary, ['before_attach', 'after_attach', 'before_commit', 'before_flush', - 'after_begin', 'after_flush', 'after_flush_postexec', - 'after_commit', 'before_attach', 'after_attach', 'before_commit', - 'before_flush', 'after_begin', 'after_rollback', - 'after_soft_rollback', 'after_soft_rollback']) + eq_(canary, + + ['before_attach', 'after_attach', 'before_commit', 'before_flush', + 'after_transaction_create', 'after_begin', 'after_flush', + 'after_flush_postexec', 'after_transaction_end', 'after_commit', + 'after_transaction_end', 'after_transaction_create', + 'before_attach', 'after_attach', 'before_commit', + 'before_flush', 'after_transaction_create', 'after_begin', 'after_rollback', + 'after_transaction_end', + 'after_soft_rollback', 'after_transaction_end','after_transaction_create', + 'after_soft_rollback']) def test_can_use_session_in_outer_rollback_hook(self): User, users = self.classes.User, self.tables.users @@ -640,8 +649,10 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): u = User(name='u1') sess.add(u) sess.flush() - eq_(canary, ['before_attach', 'after_attach', 'before_flush', 'after_begin', - 'after_flush', 'after_flush_postexec']) + eq_(canary, ['before_attach', 'after_attach', 'before_flush', + 'after_transaction_create', 'after_begin', + 'after_flush', 'after_flush_postexec', + 'after_transaction_end']) def test_flush_in_commit_hook(self): User, users = self.classes.User, self.tables.users @@ -656,8 +667,11 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): u.name = 'ed' sess.commit() - eq_(canary, ['before_commit', 'before_flush', 'after_flush', - 'after_flush_postexec', 'after_commit']) + eq_(canary, ['before_commit', 'before_flush', 'after_transaction_create', 'after_flush', + 'after_flush_postexec', + 'after_transaction_end', + 'after_commit', + 'after_transaction_end', 'after_transaction_create',]) def test_state_before_attach(self): User, users = self.classes.User, self.tables.users @@ -700,7 +714,9 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): def test_standalone_on_commit_hook(self): sess, canary = self._listener_fixture() sess.commit() - eq_(canary, ['before_commit', 'after_commit']) + eq_(canary, ['before_commit', 'after_commit', + 'after_transaction_end', + 'after_transaction_create']) def test_on_bulk_update_hook(self): User, users = self.classes.User, self.tables.users