|
1 | 1 | import threading
|
2 | 2 | from functools import partial
|
3 | 3 |
|
| 4 | +import django |
4 | 5 | from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
|
5 | 6 | from django.db import connections
|
6 | 7 | from django.db.backends.base.creation import TEST_DATABASE_PREFIX
|
7 | 8 | from django.test.testcases import TransactionTestCase
|
8 | 9 | from django.test.utils import modify_settings
|
9 | 10 | from django.utils.functional import classproperty
|
| 11 | +from django.utils.version import PY311 |
10 | 12 |
|
11 | 13 | from channels.routing import get_default_application
|
12 | 14 |
|
| 15 | +if not (PY311 or django.VERSION >= (5, 1)): |
| 16 | + # Backport of unittest.case._enter_context() from Python 3.11. |
| 17 | + def _enter_context(cm, addcleanup): |
| 18 | + # Look up the special methods on the type to match the with statement. |
| 19 | + cls = type(cm) |
| 20 | + try: |
| 21 | + enter = cls.__enter__ |
| 22 | + exit = cls.__exit__ |
| 23 | + except AttributeError: |
| 24 | + raise TypeError( |
| 25 | + f"'{cls.__module__}.{cls.__qualname__}' object does not support the " |
| 26 | + f"context manager protocol" |
| 27 | + ) from None |
| 28 | + result = enter(cm) |
| 29 | + addcleanup(exit, cm, None, None, None) |
| 30 | + return result |
| 31 | + |
13 | 32 |
|
14 | 33 | def make_application(*, static_wrapper):
|
15 | 34 | # Module-level function for pickle-ability
|
@@ -124,6 +143,12 @@ class ChannelsLiveServerTestCase(TransactionTestCase):
|
124 | 143 | static_handler = ASGIStaticFilesHandler
|
125 | 144 | serve_static = True
|
126 | 145 |
|
| 146 | + if not PY311: |
| 147 | + # Backport of unittest.TestCase.enterClassContext() from Python 3.11. |
| 148 | + @classmethod |
| 149 | + def enterClassContext(cls, cm): |
| 150 | + return _enter_context(cm, cls.addClassCleanup) |
| 151 | + |
127 | 152 | @classproperty
|
128 | 153 | def live_server_url(cls):
|
129 | 154 | return "http://%s:%s" % (cls.host, cls.server_thread.port)
|
@@ -193,11 +218,6 @@ def _terminate_thread(cls):
|
193 | 218 | for conn in cls.server_thread.connections_override.values():
|
194 | 219 | conn.dec_thread_sharing()
|
195 | 220 |
|
196 |
| - @classmethod |
197 |
| - def tearDownClass(cls): |
198 |
| - # The cleanup is now handled by addClassCleanup in _start_server_thread |
199 |
| - super().tearDownClass() |
200 |
| - |
201 | 221 | @classmethod
|
202 | 222 | def _is_in_memory_db(cls, connection):
|
203 | 223 | """
|
|
0 commit comments