Ticket #37064: remove-databases-failures-isinstance-guard.diff
| File remove-databases-failures-isinstance-guard.diff, 3.6 KB (added by , 2 hours ago) |
|---|
-
django/test/testcases.py
diff --git a/django/test/testcases.py b/django/test/testcases.py index f866a33..5d312d4 100644
a b class SimpleTestCase(unittest.TestCase): 278 278 ) 279 279 for name, _ in disallowed_methods: 280 280 method = getattr(connection, name) 281 setattr(connection, name, method.wrapped) 281 if isinstance(method, _DatabaseFailure): 282 setattr(connection, name, method.wrapped) 282 283 283 284 @classmethod 284 285 def ensure_connection_patch_method(cls): -
docs/releases/6.0.5.txt
diff --git a/docs/releases/6.0.5.txt b/docs/releases/6.0.5.txt index 7e54cbe..9fecc1e 100644
a b Bugfixes 13 13 ``django/contrib/admin/templates/admin/change_list.html`` template added in 14 14 Django 6.0 that could be problematic when overriding the ``pagination`` block 15 15 (:ticket:`37029`). 16 17 * Fixed a crash in ``SimpleTestCase._remove_databases_failures()`` when a 18 disallowed connection method was replaced between ``setUpClass()`` and 19 ``tearDownClass()`` (e.g. due to connection recycling), which raised 20 ``AttributeError: 'function' object has no attribute 'wrapped'`` during 21 teardown. -
tests/test_utils/test_simpletestcase.py
diff --git a/tests/test_utils/test_simpletestcase.py b/tests/test_utils/test_simpletestcase.py index c09c68d..a41def6 100644
a b from io import StringIO 4 4 from unittest import mock 5 5 from unittest.suite import _DebugResult 6 6 7 from django.db import connections 7 8 from django.test import SimpleTestCase 9 from django.test.testcases import _DatabaseFailure 8 10 9 11 10 12 class ErrorTestCase(SimpleTestCase): … … class DebugInvocationTests(SimpleTestCase): 147 149 self.assertFalse(_post_teardown.called) 148 150 self.assertFalse(_pre_setup.called) 149 151 self.isolate_debug_test(test_suite, result) 152 153 154 class RemoveDatabasesFailuresTests(SimpleTestCase): 155 """Regression tests for SimpleTestCase._remove_databases_failures.""" 156 157 databases = {"default"} 158 159 def _pick_other_alias(self): 160 for alias in connections: 161 if alias != "default": 162 return alias 163 self.skipTest("Test requires a second database alias.") 164 165 def test_teardown_noops_when_method_is_not_wrapped(self): 166 """ 167 If a connection method is replaced between setUpClass and 168 tearDownClass (e.g. the connection was recycled), teardown must 169 not crash with AttributeError on ``method.wrapped``. 170 """ 171 alias = self._pick_other_alias() 172 connection = connections[alias] 173 name, _ = next( 174 iter(connection.features.disallowed_simple_test_case_connection_methods) 175 ) 176 original = getattr(connection, name) 177 try: 178 setattr(connection, name, lambda *a, **kw: None) 179 self.__class__._remove_databases_failures() 180 finally: 181 setattr(connection, name, original) 182 183 def test_teardown_still_unwraps_database_failures(self): 184 """The happy path must continue to restore wrapped methods.""" 185 alias = self._pick_other_alias() 186 connection = connections[alias] 187 name, _ = next( 188 iter(connection.features.disallowed_simple_test_case_connection_methods) 189 ) 190 original = getattr(connection, name) 191 setattr(connection, name, _DatabaseFailure(original, "msg")) 192 try: 193 self.__class__._remove_databases_failures() 194 self.assertIs(getattr(connection, name), original) 195 finally: 196 setattr(connection, name, original)