From 8cc35f6d65312b68cb3c663c261f07a6c484f1ad Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 10 Feb 2007 23:45:08 +0000 Subject: [PATCH] - added support for py2.5 "with" statement with SessionTransaction [ticket:468] --- CHANGES | 1 + doc/build/content/unitofwork.txt | 10 ++++++++++ lib/sqlalchemy/orm/session.py | 11 ++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ae46d90282..fc59d0b851 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ items in the cascade [ticket:445] - fix to deferred so that load operation doesnt mistakenly occur when only PK col attributes are set + - added support for py2.5 "with" statement with SessionTransaction [ticket:468] - oracle: - when returning "rowid" as the ORDER BY column or in use with ROW_NUMBER OVER, oracle dialect checks the selectable its being applied to and will switch to diff --git a/doc/build/content/unitofwork.txt b/doc/build/content/unitofwork.txt index 9d0e732f9d..ddf4bbe473 100644 --- a/doc/build/content/unitofwork.txt +++ b/doc/build/content/unitofwork.txt @@ -370,6 +370,16 @@ Example usage is as follows: raise trans.commit() +The SessionTransaction object supports Python 2.5's with statement so that the example above can be written as: + + {python} + sess = create_session() + with sess.create_transaction(): + item1 = sess.query(Item).get(1) + item2 = sess.query(Item).get(2) + item1.foo = 'bar' + item2.bar = 'foo' + The `create_transaction()` method creates a new SessionTransaction object but does not declare any connection/transaction resources. At the point of the first `get()` call, a connection resource is opened off the engine that corresponds to the Item classes' mapper and is stored within the `SessionTransaction` with an open `Transaction`. When `trans.commit()` is called, the `flush()` method is called on the `Session` and the corresponding update statements are issued to the database within the scope of the transaction already opened; afterwards, the underying Transaction is committed, and connection resources are freed. `SessionTransaction`, like the `Transaction` off of `Connection` also supports "nested" behavior, and is safe to pass to other functions which then issue their own `begin()`/`commit()` pair; only the outermost `begin()`/`commit()` pair actually affects the transaction, and any call to `rollback()` within a particular call stack will issue a rollback. diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index f2a7181774..4935b04819 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -69,6 +69,15 @@ class SessionTransaction(object): if t[2]: t[0].close() self.session.transaction = None + def __enter__(self): + return self + def __exit__(self, type, value, traceback): + if self.session.transaction is None: + return + if type is None: + self.commit() + else: + self.rollback() class Session(object): """encapsulates a set of objects being operated upon within an object-relational operation. @@ -452,4 +461,4 @@ def object_session(obj): unitofwork.object_session = object_session from sqlalchemy.orm import mapper -mapper.attribute_manager = attribute_manager \ No newline at end of file +mapper.attribute_manager = attribute_manager -- 2.47.2