summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-09-20 18:39:27 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-09-20 18:39:27 -0400
commit248cf4c5d2f227c7cc49772f023807aebeb5c969 (patch)
tree1305b8a8db9203093d9ddf9e26f0bc5bc7a26cf1
parente5accce97bae1b35eeb1eb26f8281a98c58d2cef (diff)
downloadsqlalchemy-248cf4c5d2f227c7cc49772f023807aebeb5c969.tar.gz
- [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.
-rw-r--r--CHANGES7
-rw-r--r--lib/sqlalchemy/orm/events.py20
-rw-r--r--lib/sqlalchemy/orm/session.py10
-rw-r--r--test/orm/test_events.py40
4 files changed, 64 insertions, 13 deletions
diff --git a/CHANGES b/CHANGES
index 5ac1b4d34..f8991bd03 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 67f6d6431..61517770f 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 e0f79cd8a..36ff5fc84 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 bf413125a..e49a4a6a7 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