Ticket #37064: remove-databases-failures-isinstance-guard.diff

File remove-databases-failures-isinstance-guard.diff, 3.6 KB (added by Rio Weber, 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):  
    278278            )
    279279            for name, _ in disallowed_methods:
    280280                method = getattr(connection, name)
    281                 setattr(connection, name, method.wrapped)
     281                if isinstance(method, _DatabaseFailure):
     282                    setattr(connection, name, method.wrapped)
    282283
    283284    @classmethod
    284285    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  
    1313  ``django/contrib/admin/templates/admin/change_list.html`` template added in
    1414  Django 6.0 that could be problematic when overriding the ``pagination`` block
    1515  (: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  
    44from unittest import mock
    55from unittest.suite import _DebugResult
    66
     7from django.db import connections
    78from django.test import SimpleTestCase
     9from django.test.testcases import _DatabaseFailure
    810
    911
    1012class ErrorTestCase(SimpleTestCase):
    class DebugInvocationTests(SimpleTestCase):  
    147149        self.assertFalse(_post_teardown.called)
    148150        self.assertFalse(_pre_setup.called)
    149151        self.isolate_debug_test(test_suite, result)
     152
     153
     154class 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)
Back to Top