From: plumSemPy Date: Wed, 4 Jan 2017 17:06:48 +0000 (-0500) Subject: Ensure session.no_autoflush uses finally X-Git-Tag: rel_1_1_5~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd95d4a5b928a6bc4f07c988ba3791a0a63c8d15;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Ensure session.no_autoflush uses finally The :attr:`.Session.no_autoflush` context manager now ensures that the autoflush flag is reset within a "finally" block, so that if an exception is raised within the block, the state still resets appropriately. Pull request courtesy Emin Arakelian. Change-Id: Ib19ddf32074b1df82a6a1f1ae14e3a962cd31a5f Pull-request: https://github.com/zzzeek/sqlalchemy/pull/335 --- diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 972c1d1df6..3fed21b170 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,14 @@ .. changelog:: :version: 1.1.5 + .. change:: try_finally_for_noautoflush + :tags: bug, orm + + The :attr:`.Session.no_autoflush` context manager now ensures that + the autoflush flag is reset within a "finally" block, so that if + an exception is raised within the block, the state still resets + appropriately. Pull request courtesy Emin Arakelian. + .. change:: 3878 :tags: bug, sql :tickets: 3878 diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index b39ba1465a..cb1ebf0130 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1354,8 +1354,10 @@ class Session(_SessionClassMethods): """ autoflush = self.autoflush self.autoflush = False - yield self - self.autoflush = autoflush + try: + yield self + finally: + self.autoflush = autoflush def _autoflush(self): if self.autoflush and not self._flushing: diff --git a/test/orm/test_session.py b/test/orm/test_session.py index 24666d084c..5cc8aec208 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -1,5 +1,5 @@ from sqlalchemy.testing import eq_, assert_raises, \ - assert_raises_message, assertions + assert_raises_message, assertions, is_true from sqlalchemy.testing.util import gc_collect from sqlalchemy.testing import pickleable from sqlalchemy.util import pickle @@ -317,6 +317,17 @@ class SessionStateTest(_fixtures.FixtureTest): assert u in sess.query(User).all() assert u not in sess.new + def test_with_no_autoflush_after_exception(self): + sess = Session(autoflush=True) + + assert_raises( + ZeroDivisionError, + testing.run_as_contextmanager, + sess.no_autoflush, + lambda obj: 1 / 0 + ) + + is_true(sess.autoflush) def test_deleted_flag(self): users, User = self.tables.users, self.classes.User