summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-02-25 14:34:02 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-02-25 14:34:02 -0500
commitdeb7e76a42fac9995174f30baa365b4d03ddee3c (patch)
treea0f765595d9df4231eda13dd78bef21c94df43bd
parentabe6c0f08a49859d8a2c36f4011e6f81ebf7ecb2 (diff)
downloadsqlalchemy-deb7e76a42fac9995174f30baa365b4d03ddee3c.tar.gz
- [feature] Added "no_autoflush" context
manager to Session, used with with: will temporarily disable autoflush.
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/orm/session.py28
-rw-r--r--lib/sqlalchemy/util/__init__.py2
-rw-r--r--lib/sqlalchemy/util/compat.py6
-rw-r--r--test/orm/test_session.py17
5 files changed, 56 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index d45f616a0..867ed0118 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@ CHANGES
0.7.6
=====
- orm
+ - [feature] Added "no_autoflush" context
+ manager to Session, used with with:
+ will temporarily disable autoflush.
+
- [bug] Fixed bug whereby MappedCollection
would not get the appropriate collection
instrumentation if it were only used
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index ba6ceaeec..d01c1598a 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -978,6 +978,34 @@ class Session(object):
return self._query_cls(entities, self, **kwargs)
+ @property
+ @util.contextmanager
+ def no_autoflush(self):
+ """Return a context manager that disables autoflush.
+
+ e.g.::
+
+ with session.no_autoflush:
+
+ some_object = SomeClass()
+ session.add(some_object)
+ # won't autoflush
+ some_object.related_thing = session.query(SomeRelated).first()
+
+ Operations that proceed within the ``with:`` block
+ will not be subject to flushes occurring upon query
+ access. This is useful when initializing a series
+ of objects which involve existing database queries,
+ where the uncompleted object should not yet be flushed.
+
+ New in 0.7.6.
+
+ """
+ autoflush = self.autoflush
+ self.autoflush = False
+ yield self
+ self.autoflush = autoflush
+
def _autoflush(self):
if self.autoflush and not self._flushing:
self.flush()
diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py
index 571294025..13914aa7d 100644
--- a/lib/sqlalchemy/util/__init__.py
+++ b/lib/sqlalchemy/util/__init__.py
@@ -7,7 +7,7 @@
from compat import callable, cmp, reduce, defaultdict, py25_dict, \
threading, py3k_warning, jython, pypy, win32, set_types, buffer, pickle, \
update_wrapper, partial, md5_hex, decode_slice, dottedgetter,\
- parse_qsl, any
+ parse_qsl, any, contextmanager
from _collections import NamedTuple, ImmutableContainer, immutabledict, \
Properties, OrderedProperties, ImmutableProperties, OrderedDict, \
diff --git a/lib/sqlalchemy/util/compat.py b/lib/sqlalchemy/util/compat.py
index 07652f3c6..99b92b1e3 100644
--- a/lib/sqlalchemy/util/compat.py
+++ b/lib/sqlalchemy/util/compat.py
@@ -57,6 +57,12 @@ buffer = buffer
# end Py2K
try:
+ from contextlib import contextmanager
+except ImportError:
+ def contextmanager(fn):
+ return fn
+
+try:
from functools import update_wrapper
except ImportError:
def update_wrapper(wrapper, wrapped,
diff --git a/test/orm/test_session.py b/test/orm/test_session.py
index ac22455bd..79852c7a4 100644
--- a/test/orm/test_session.py
+++ b/test/orm/test_session.py
@@ -222,6 +222,23 @@ class SessionTest(_fixtures.FixtureTest):
eq_(bind.connect().execute("select count(1) from users").scalar(), 1)
sess.close()
+ @testing.requires.python26
+ def test_with_no_autoflush(self):
+ User, users = self.classes.User, self.tables.users
+
+ mapper(User, users)
+ sess = Session()
+
+ u = User()
+ u.name = 'ed'
+ sess.add(u)
+ def go(obj):
+ assert u not in sess.query(User).all()
+ testing.run_as_contextmanager(sess.no_autoflush, go)
+ assert u in sess.new
+ assert u in sess.query(User).all()
+ assert u not in sess.new
+
def test_make_transient(self):
users, User = self.tables.users, self.classes.User