Ticket #6623: 6623-4.diff

File 6623-4.diff, 4.4 KB (added by Claude Paroz, 12 years ago)

Patch updated and with tests

  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index ebe8875..ec8a755 100644
    a b class BaseDatabaseWrapper(object):  
    102102            self._dirty = False
    103103        self._enter_transaction_management(managed)
    104104
    105     def leave_transaction_management(self):
     105    def leave_transaction_management(self, exception=None):
    106106        """
    107107        Leaves transaction management for a running thread. A dirty flag is carried
    108108        over to the surrounding block, as a commit will commit all changes, even
    109109        those from outside. (Commits are on connection level.)
     110
     111        If this function is called from within a finally block where an
     112        exception is in the process of working its way up the stack, pass
     113        the exception argument so we don't raise a new exception over the
     114        pending one.
    110115        """
    111116        self._leave_transaction_management(self.is_managed())
    112117        if self.transaction_state:
    class BaseDatabaseWrapper(object):  
    116121                "management")
    117122        if self._dirty:
    118123            self.rollback()
    119             raise TransactionManagementError("Transaction managed block ended with "
    120                 "pending COMMIT/ROLLBACK")
     124            if exception is None:
     125                raise TransactionManagementError("Transaction managed block "
     126                "ended with pending COMMIT/ROLLBACK")
    121127        self._dirty = False
    122128
    123129    def validate_thread_sharing(self):
  • django/db/transaction.py

    diff --git a/django/db/transaction.py b/django/db/transaction.py
    index 4ecd2d1..aa01ba4 100644
    a b def enter_transaction_management(managed=True, using=None):  
    4040    connection = connections[using]
    4141    connection.enter_transaction_management(managed)
    4242
    43 def leave_transaction_management(using=None):
     43def leave_transaction_management(using=None, exception=None):
    4444    """
    4545    Leaves transaction management for a running thread. A dirty flag is carried
    4646    over to the surrounding block, as a commit will commit all changes, even
    def leave_transaction_management(using=None):  
    4949    if using is None:
    5050        using = DEFAULT_DB_ALIAS
    5151    connection = connections[using]
    52     connection.leave_transaction_management()
     52    connection.leave_transaction_management(exception)
    5353
    5454def is_dirty(using=None):
    5555    """
    def commit_manually(using=None):  
    285285        managed(True, using=using)
    286286
    287287    def exiting(exc_value, using):
    288         leave_transaction_management(using=using)
     288        leave_transaction_management(using=using, exception=exc_value)
    289289
    290290    return _transaction_func(entering, exiting, using)
  • tests/regressiontests/transactions_regress/tests.py

    diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py
    index 5972263..7b39905 100644
    a b  
    11from __future__ import absolute_import
    22
    3 from django.core.exceptions import ImproperlyConfigured
     3from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
    44from django.db import connection, transaction
    55from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
    66from django.test import TransactionTestCase, skipUnlessDBFeature
    class TestTransactionClosing(TransactionTestCase):  
    175175        self.test_failing_query_transaction_closed()
    176176
    177177
     178class TestExceptionDuringTransaction(TransactionTestCase):
     179    """ When an exception happens during a transaction, the transaction should
     180        not swallow the original exception and replace it by a
     181        TransactionManagementError. The original exception should have priority.
     182    """
     183
     184    def test_commit_manually_exception_raised(self):
     185        @commit_manually
     186        def fun_with_exception():
     187            _ = Mod.objects.get(fld=777)
     188
     189        self.assertRaises(ObjectDoesNotExist, fun_with_exception)
     190
     191    def test_commit_on_success_exception_raised(self):
     192        @commit_on_success
     193        def fun_with_exception():
     194            _ = Mod.objects.get(fld=777)
     195
     196        self.assertRaises(ObjectDoesNotExist, fun_with_exception)
     197
     198
    178199class TestManyToManyAddTransaction(TransactionTestCase):
    179200    def test_manyrelated_add_commit(self):
    180201        "Test for https://code.djangoproject.com/ticket/16818"
Back to Top