From 7aacde84f2b499d9c35741cbfccb621af6b48903 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sat, 2 Mar 2013 20:25:25 +0100 Subject: [PATCH] Made transaction.managed a no-op and deprecated it. enter_transaction_management() was nearly always followed by managed(). In three places it wasn't, but they will all be refactored eventually. The "forced" keyword argument avoids introducing behavior changes until then. This is mostly backwards-compatible, except, of course, for managed itself. There's a minor difference in _enter_transaction_management: the top self.transaction_state now contains the new 'managed' state rather than the previous one. Django doesn't access self.transaction_state in _enter_transaction_management. --- django/core/management/commands/loaddata.py | 1 - django/db/backends/__init__.py | 29 +++++---------------- django/db/models/deletion.py | 2 +- django/db/models/query.py | 4 +-- django/db/transaction.py | 18 +++++-------- django/middleware/transaction.py | 1 - django/test/testcases.py | 4 --- docs/internals/deprecation.txt | 6 +++-- tests/delete_regress/tests.py | 4 +-- tests/middleware/tests.py | 6 +---- tests/requests/tests.py | 2 -- tests/select_for_update/tests.py | 3 --- tests/serializers/tests.py | 1 - tests/transactions_regress/tests.py | 5 ---- 14 files changed, 22 insertions(+), 64 deletions(-) diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index ed47b8fbf1..77b9a44a43 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -75,7 +75,6 @@ class Command(BaseCommand): if commit: transaction.commit_unless_managed(using=self.using) transaction.enter_transaction_management(using=self.using) - transaction.managed(True, using=self.using) class SingleZipReader(zipfile.ZipFile): def __init__(self, *args, **kwargs): diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index fe26c98baf..f11ee35260 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -234,7 +234,7 @@ class BaseDatabaseWrapper(object): ##### Generic transaction management methods ##### - def enter_transaction_management(self, managed=True): + def enter_transaction_management(self, managed=True, forced=False): """ Enters transaction management for a running thread. It must be balanced with the appropriate leave_transaction_management call, since the actual state is @@ -243,12 +243,14 @@ class BaseDatabaseWrapper(object): The state and dirty flag are carried over from the surrounding block or from the settings, if there is no surrounding block (dirty is always false when no current block is running). + + If you switch off transaction management and there is a pending + commit/rollback, the data will be commited, unless "forced" is True. """ - if self.transaction_state: - self.transaction_state.append(self.transaction_state[-1]) - else: - self.transaction_state.append(settings.TRANSACTIONS_MANAGED) + self.transaction_state.append(managed) self._enter_transaction_management(managed) + if not managed and self.is_dirty() and not forced: + self.commit() def leave_transaction_management(self): """ @@ -314,22 +316,6 @@ class BaseDatabaseWrapper(object): return self.transaction_state[-1] return settings.TRANSACTIONS_MANAGED - def managed(self, flag=True): - """ - Puts the transaction manager into a manual state: managed transactions have - to be committed explicitly by the user. If you switch off transaction - management and there is a pending commit/rollback, the data will be - commited. - """ - top = self.transaction_state - if top: - top[-1] = flag - if not flag and self.is_dirty(): - self.commit() - else: - raise TransactionManagementError("This code isn't under transaction " - "management") - def commit_unless_managed(self): """ Commits changes if the system is not in managed transaction mode. @@ -574,7 +560,6 @@ class BaseDatabaseFeatures(object): # otherwise autocommit will cause the confimation to # fail. self.connection.enter_transaction_management() - self.connection.managed(True) cursor = self.connection.cursor() cursor.execute('CREATE TABLE ROLLBACK_TEST (X INT)') self.connection.commit() diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py index 81f74923c2..93ef0006cb 100644 --- a/django/db/models/deletion.py +++ b/django/db/models/deletion.py @@ -54,7 +54,7 @@ def force_managed(func): @wraps(func) def decorated(self, *args, **kwargs): if not transaction.is_managed(using=self.using): - transaction.enter_transaction_management(using=self.using) + transaction.enter_transaction_management(using=self.using, forced=True) forced_managed = True else: forced_managed = False diff --git a/django/db/models/query.py b/django/db/models/query.py index 30be30ca43..b41007ee4f 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -443,7 +443,7 @@ class QuerySet(object): connection = connections[self.db] fields = self.model._meta.local_fields if not transaction.is_managed(using=self.db): - transaction.enter_transaction_management(using=self.db) + transaction.enter_transaction_management(using=self.db, forced=True) forced_managed = True else: forced_managed = False @@ -582,7 +582,7 @@ class QuerySet(object): query = self.query.clone(sql.UpdateQuery) query.add_update_values(kwargs) if not transaction.is_managed(using=self.db): - transaction.enter_transaction_management(using=self.db) + transaction.enter_transaction_management(using=self.db, forced=True) forced_managed = True else: forced_managed = False diff --git a/django/db/transaction.py b/django/db/transaction.py index 809f14f628..09ce2abbd2 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -12,6 +12,8 @@ Managed transactions don't do those commits, but will need some kind of manual or implicit commits or rollbacks. """ +import warnings + from functools import wraps from django.db import connections, DEFAULT_DB_ALIAS @@ -49,7 +51,7 @@ def abort(using=None): """ get_connection(using).abort() -def enter_transaction_management(managed=True, using=None): +def enter_transaction_management(managed=True, using=None, forced=False): """ Enters transaction management for a running thread. It must be balanced with the appropriate leave_transaction_management call, since the actual state is @@ -59,7 +61,7 @@ def enter_transaction_management(managed=True, using=None): from the settings, if there is no surrounding block (dirty is always false when no current block is running). """ - get_connection(using).enter_transaction_management(managed) + get_connection(using).enter_transaction_management(managed, forced) def leave_transaction_management(using=None): """ @@ -105,13 +107,8 @@ def is_managed(using=None): return get_connection(using).is_managed() def managed(flag=True, using=None): - """ - Puts the transaction manager into a manual state: managed transactions have - to be committed explicitly by the user. If you switch off transaction - management and there is a pending commit/rollback, the data will be - commited. - """ - get_connection(using).managed(flag) + warnings.warn("'managed' no longer serves a purpose.", + PendingDeprecationWarning, stacklevel=2) def commit_unless_managed(using=None): """ @@ -224,7 +221,6 @@ def autocommit(using=None): """ def entering(using): enter_transaction_management(managed=False, using=using) - managed(False, using=using) def exiting(exc_value, using): leave_transaction_management(using=using) @@ -240,7 +236,6 @@ def commit_on_success(using=None): """ def entering(using): enter_transaction_management(using=using) - managed(True, using=using) def exiting(exc_value, using): try: @@ -268,7 +263,6 @@ def commit_manually(using=None): """ def entering(using): enter_transaction_management(using=using) - managed(True, using=using) def exiting(exc_value, using): leave_transaction_management(using=using) diff --git a/django/middleware/transaction.py b/django/middleware/transaction.py index 4440f377a7..b5a07a02b7 100644 --- a/django/middleware/transaction.py +++ b/django/middleware/transaction.py @@ -10,7 +10,6 @@ class TransactionMiddleware(object): def process_request(self, request): """Enters transaction management""" transaction.enter_transaction_management() - transaction.managed(True) def process_exception(self, request, exception): """Rolls back the database and leaves transaction management""" diff --git a/django/test/testcases.py b/django/test/testcases.py index 44ddb624d6..7f6b1a49ba 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -67,7 +67,6 @@ real_commit = transaction.commit real_rollback = transaction.rollback real_enter_transaction_management = transaction.enter_transaction_management real_leave_transaction_management = transaction.leave_transaction_management -real_managed = transaction.managed real_abort = transaction.abort def nop(*args, **kwargs): @@ -78,7 +77,6 @@ def disable_transaction_methods(): transaction.rollback = nop transaction.enter_transaction_management = nop transaction.leave_transaction_management = nop - transaction.managed = nop transaction.abort = nop def restore_transaction_methods(): @@ -86,7 +84,6 @@ def restore_transaction_methods(): transaction.rollback = real_rollback transaction.enter_transaction_management = real_enter_transaction_management transaction.leave_transaction_management = real_leave_transaction_management - transaction.managed = real_managed transaction.abort = real_abort @@ -833,7 +830,6 @@ class TestCase(TransactionTestCase): for db_name in self._databases_names(): transaction.enter_transaction_management(using=db_name) - transaction.managed(True, using=db_name) disable_transaction_methods() from django.contrib.sites.models import Site diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index b5173af298..296f908a5b 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -339,8 +339,6 @@ these changes. * ``Model._meta.module_name`` was renamed to ``model_name``. -* The private API ``django.db.close_connection`` will be removed. - * Remove the backward compatible shims introduced to rename ``get_query_set`` and similar queryset methods. This affects the following classes: ``BaseModelAdmin``, ``ChangeList``, ``BaseCommentNode``, @@ -350,6 +348,10 @@ these changes. * Remove the backward compatible shims introduced to rename the attributes ``ChangeList.root_query_set`` and ``ChangeList.query_set``. +* The private API ``django.db.close_connection`` will be removed. + +* The private API ``django.transaction.managed`` will be removed. + 2.0 --- diff --git a/tests/delete_regress/tests.py b/tests/delete_regress/tests.py index 9fcc19ba71..e88c95e229 100644 --- a/tests/delete_regress/tests.py +++ b/tests/delete_regress/tests.py @@ -22,9 +22,7 @@ class DeleteLockingTest(TransactionTestCase): self.conn2 = new_connections[DEFAULT_DB_ALIAS] # Put both DB connections into managed transaction mode transaction.enter_transaction_management() - transaction.managed(True) self.conn2.enter_transaction_management() - self.conn2.managed(True) def tearDown(self): # Close down the second connection. @@ -335,7 +333,7 @@ class Ticket19102Tests(TestCase): ).select_related('orgunit').delete() self.assertFalse(Login.objects.filter(pk=self.l1.pk).exists()) self.assertTrue(Login.objects.filter(pk=self.l2.pk).exists()) - + @skipUnlessDBFeature("update_can_self_select") def test_ticket_19102_defer(self): with self.assertNumQueries(1): diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py index 4e5fd8ea6b..122371c02c 100644 --- a/tests/middleware/tests.py +++ b/tests/middleware/tests.py @@ -692,7 +692,6 @@ class TransactionMiddlewareTest(TransactionTestCase): def test_managed_response(self): transaction.enter_transaction_management() - transaction.managed(True) Band.objects.create(name='The Beatles') self.assertTrue(transaction.is_dirty()) TransactionMiddleware().process_response(self.request, self.response) @@ -700,8 +699,7 @@ class TransactionMiddlewareTest(TransactionTestCase): self.assertEqual(Band.objects.count(), 1) def test_unmanaged_response(self): - transaction.enter_transaction_management() - transaction.managed(False) + transaction.enter_transaction_management(False) self.assertEqual(Band.objects.count(), 0) TransactionMiddleware().process_response(self.request, self.response) self.assertFalse(transaction.is_managed()) @@ -711,7 +709,6 @@ class TransactionMiddlewareTest(TransactionTestCase): def test_exception(self): transaction.enter_transaction_management() - transaction.managed(True) Band.objects.create(name='The Beatles') self.assertTrue(transaction.is_dirty()) TransactionMiddleware().process_exception(self.request, None) @@ -726,7 +723,6 @@ class TransactionMiddlewareTest(TransactionTestCase): raise IntegrityError() connections[DEFAULT_DB_ALIAS].commit = raise_exception transaction.enter_transaction_management() - transaction.managed(True) Band.objects.create(name='The Beatles') self.assertTrue(transaction.is_dirty()) with self.assertRaises(IntegrityError): diff --git a/tests/requests/tests.py b/tests/requests/tests.py index 4fdc17618b..2803d7995b 100644 --- a/tests/requests/tests.py +++ b/tests/requests/tests.py @@ -576,7 +576,6 @@ class DatabaseConnectionHandlingTests(TransactionTestCase): # Make sure there is an open connection connection.cursor() connection.enter_transaction_management() - connection.managed(True) signals.request_finished.send(sender=response._handler_class) self.assertEqual(len(connection.transaction_state), 0) @@ -585,7 +584,6 @@ class DatabaseConnectionHandlingTests(TransactionTestCase): connection.settings_dict['CONN_MAX_AGE'] = 0 connection.enter_transaction_management() - connection.managed(True) connection.set_dirty() # Test that the rollback doesn't succeed (for example network failure # could cause this). diff --git a/tests/select_for_update/tests.py b/tests/select_for_update/tests.py index b9716bd797..c2fa22705a 100644 --- a/tests/select_for_update/tests.py +++ b/tests/select_for_update/tests.py @@ -25,7 +25,6 @@ class SelectForUpdateTests(TransactionTestCase): def setUp(self): transaction.enter_transaction_management() - transaction.managed(True) self.person = Person.objects.create(name='Reinhardt') # We have to commit here so that code in run_select_for_update can @@ -37,7 +36,6 @@ class SelectForUpdateTests(TransactionTestCase): new_connections = ConnectionHandler(settings.DATABASES) self.new_connection = new_connections[DEFAULT_DB_ALIAS] self.new_connection.enter_transaction_management() - self.new_connection.managed(True) # We need to set settings.DEBUG to True so we can capture # the output SQL to examine. @@ -162,7 +160,6 @@ class SelectForUpdateTests(TransactionTestCase): # We need to enter transaction management again, as this is done on # per-thread basis transaction.enter_transaction_management() - transaction.managed(True) people = list( Person.objects.all().select_for_update(nowait=nowait) ) diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py index 34d0f5f1b1..a96a1af748 100644 --- a/tests/serializers/tests.py +++ b/tests/serializers/tests.py @@ -268,7 +268,6 @@ class SerializersTransactionTestBase(object): # within a transaction in order to test forward reference # handling. transaction.enter_transaction_management() - transaction.managed(True) objs = serializers.deserialize(self.serializer_name, self.fwd_ref_str) with connection.constraint_checks_disabled(): for obj in objs: diff --git a/tests/transactions_regress/tests.py b/tests/transactions_regress/tests.py index 6ba04892cd..0af7605339 100644 --- a/tests/transactions_regress/tests.py +++ b/tests/transactions_regress/tests.py @@ -223,7 +223,6 @@ class TestNewConnection(TransactionTestCase): def test_commit_unless_managed_in_managed(self): cursor = connection.cursor() connection.enter_transaction_management() - transaction.managed(True) cursor.execute("INSERT into transactions_regress_mod (fld) values (2)") connection.commit_unless_managed() self.assertTrue(connection.is_dirty()) @@ -280,7 +279,6 @@ class TestPostgresAutocommitAndIsolation(TransactionTestCase): def test_transaction_management(self): transaction.enter_transaction_management() - transaction.managed(True) self.assertEqual(connection.isolation_level, self._serializable) transaction.leave_transaction_management() @@ -288,7 +286,6 @@ class TestPostgresAutocommitAndIsolation(TransactionTestCase): def test_transaction_stacking(self): transaction.enter_transaction_management() - transaction.managed(True) self.assertEqual(connection.isolation_level, self._serializable) transaction.enter_transaction_management() @@ -302,13 +299,11 @@ class TestPostgresAutocommitAndIsolation(TransactionTestCase): def test_enter_autocommit(self): transaction.enter_transaction_management() - transaction.managed(True) self.assertEqual(connection.isolation_level, self._serializable) list(Mod.objects.all()) self.assertTrue(transaction.is_dirty()) # Enter autocommit mode again. transaction.enter_transaction_management(False) - transaction.managed(False) self.assertFalse(transaction.is_dirty()) self.assertEqual( connection.connection.get_transaction_status(),