From 3b4a5b9f97f113ca5151cff744019e39a1ed7475 Mon Sep 17 00:00:00 2001 From: David Wobrock Date: Sun, 2 Oct 2022 18:53:05 +0200 Subject: [PATCH] Fixed #23353 -- Used "raise from" when raising TransactionManagementError. This change sets the __cause__ attribute to raised exceptions. --- django/db/backends/base/base.py | 3 ++- django/db/transaction.py | 3 ++- tests/basic/tests.py | 3 ++- tests/transactions/tests.py | 5 ++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/django/db/backends/base/base.py b/django/db/backends/base/base.py index 3f07b4231a..f04bd8882a 100644 --- a/django/db/backends/base/base.py +++ b/django/db/backends/base/base.py @@ -93,6 +93,7 @@ class BaseDatabaseWrapper: # Tracks if the transaction should be rolled back to the next # available savepoint because of an exception in an inner block. self.needs_rollback = False + self.rollback_exc = None # Connection termination related attributes. self.close_at = None @@ -526,7 +527,7 @@ class BaseDatabaseWrapper: raise TransactionManagementError( "An error occurred in the current transaction. You can't " "execute queries until the end of the 'atomic' block." - ) + ) from self.rollback_exc # ##### Foreign key constraints checks handling ##### diff --git a/django/db/transaction.py b/django/db/transaction.py index e57e1d0a6f..4150cbcbbe 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -118,10 +118,11 @@ def mark_for_rollback_on_error(using=None): """ try: yield - except Exception: + except Exception as exc: connection = get_connection(using) if connection.in_atomic_block: connection.needs_rollback = True + connection.rollback_exc = exc raise diff --git a/tests/basic/tests.py b/tests/basic/tests.py index 44ace3d684..1d91e39ce9 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -805,8 +805,9 @@ class SelectOnSaveTests(TestCase): "An error occurred in the current transaction. You can't " "execute queries until the end of the 'atomic' block." ) - with self.assertRaisesMessage(DatabaseError, msg): + with self.assertRaisesMessage(DatabaseError, msg) as cm: asos.save(update_fields=["pub_date"]) + self.assertIsInstance(cm.exception.__cause__, DatabaseError) finally: Article._base_manager._queryset_class = orig_class diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py index a528ab22e5..bdf912653c 100644 --- a/tests/transactions/tests.py +++ b/tests/transactions/tests.py @@ -339,8 +339,11 @@ class AtomicErrorsTests(TransactionTestCase): "An error occurred in the current transaction. You can't " "execute queries until the end of the 'atomic' block." ) - with self.assertRaisesMessage(transaction.TransactionManagementError, msg): + with self.assertRaisesMessage( + transaction.TransactionManagementError, msg + ) as cm: r2.save(force_update=True) + self.assertIsInstance(cm.exception.__cause__, IntegrityError) self.assertEqual(Reporter.objects.get(pk=r1.pk).last_name, "Haddock") @skipIfDBFeature("atomic_transactions")