测试gitnore
This commit is contained in:
@@ -25,7 +25,6 @@ from django.db.models.options import Options
|
||||
from django.template import Template
|
||||
from django.test.signals import setting_changed, template_rendered
|
||||
from django.urls import get_script_prefix, set_script_prefix
|
||||
from django.utils.deprecation import RemovedInDjango50Warning
|
||||
from django.utils.translation import deactivate
|
||||
|
||||
try:
|
||||
@@ -35,24 +34,15 @@ except ImportError:
|
||||
|
||||
|
||||
__all__ = (
|
||||
"Approximate",
|
||||
"ContextList",
|
||||
"isolate_lru_cache",
|
||||
"get_runner",
|
||||
"CaptureQueriesContext",
|
||||
"ignore_warnings",
|
||||
"isolate_apps",
|
||||
"modify_settings",
|
||||
"override_settings",
|
||||
"override_system_checks",
|
||||
"tag",
|
||||
"requires_tz_support",
|
||||
"setup_databases",
|
||||
"setup_test_environment",
|
||||
"teardown_test_environment",
|
||||
'Approximate', 'ContextList', 'isolate_lru_cache', 'get_runner',
|
||||
'CaptureQueriesContext',
|
||||
'ignore_warnings', 'isolate_apps', 'modify_settings', 'override_settings',
|
||||
'override_system_checks', 'tag',
|
||||
'requires_tz_support',
|
||||
'setup_databases', 'setup_test_environment', 'teardown_test_environment',
|
||||
)
|
||||
|
||||
TZ_SUPPORT = hasattr(time, "tzset")
|
||||
TZ_SUPPORT = hasattr(time, 'tzset')
|
||||
|
||||
|
||||
class Approximate:
|
||||
@@ -72,7 +62,6 @@ class ContextList(list):
|
||||
A wrapper that provides direct key access to context items contained
|
||||
in a list of context objects.
|
||||
"""
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, str):
|
||||
for subcontext in self:
|
||||
@@ -120,7 +109,7 @@ def setup_test_environment(debug=None):
|
||||
Perform global pre-test setup, such as installing the instrumented template
|
||||
renderer and setting the email backend to the locmem email backend.
|
||||
"""
|
||||
if hasattr(_TestState, "saved_data"):
|
||||
if hasattr(_TestState, 'saved_data'):
|
||||
# Executing this function twice would overwrite the saved values.
|
||||
raise RuntimeError(
|
||||
"setup_test_environment() was already called and can't be called "
|
||||
@@ -135,13 +124,13 @@ def setup_test_environment(debug=None):
|
||||
|
||||
saved_data.allowed_hosts = settings.ALLOWED_HOSTS
|
||||
# Add the default host of the test client.
|
||||
settings.ALLOWED_HOSTS = [*settings.ALLOWED_HOSTS, "testserver"]
|
||||
settings.ALLOWED_HOSTS = [*settings.ALLOWED_HOSTS, 'testserver']
|
||||
|
||||
saved_data.debug = settings.DEBUG
|
||||
settings.DEBUG = debug
|
||||
|
||||
saved_data.email_backend = settings.EMAIL_BACKEND
|
||||
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
||||
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
|
||||
|
||||
saved_data.template_render = Template._render
|
||||
Template._render = instrumented_test_render
|
||||
@@ -167,18 +156,8 @@ def teardown_test_environment():
|
||||
del mail.outbox
|
||||
|
||||
|
||||
def setup_databases(
|
||||
verbosity,
|
||||
interactive,
|
||||
*,
|
||||
time_keeper=None,
|
||||
keepdb=False,
|
||||
debug_sql=False,
|
||||
parallel=0,
|
||||
aliases=None,
|
||||
serialized_aliases=None,
|
||||
**kwargs,
|
||||
):
|
||||
def setup_databases(verbosity, interactive, *, time_keeper=None, keepdb=False, debug_sql=False, parallel=0,
|
||||
aliases=None, **kwargs):
|
||||
"""Create the test databases."""
|
||||
if time_keeper is None:
|
||||
time_keeper = NullTimeKeeper()
|
||||
@@ -197,31 +176,11 @@ def setup_databases(
|
||||
if first_alias is None:
|
||||
first_alias = alias
|
||||
with time_keeper.timed(" Creating '%s'" % alias):
|
||||
# RemovedInDjango50Warning: when the deprecation ends,
|
||||
# replace with:
|
||||
# serialize_alias = (
|
||||
# serialized_aliases is None
|
||||
# or alias in serialized_aliases
|
||||
# )
|
||||
try:
|
||||
serialize_alias = connection.settings_dict["TEST"]["SERIALIZE"]
|
||||
except KeyError:
|
||||
serialize_alias = (
|
||||
serialized_aliases is None or alias in serialized_aliases
|
||||
)
|
||||
else:
|
||||
warnings.warn(
|
||||
"The SERIALIZE test database setting is "
|
||||
"deprecated as it can be inferred from the "
|
||||
"TestCase/TransactionTestCase.databases that "
|
||||
"enable the serialized_rollback feature.",
|
||||
category=RemovedInDjango50Warning,
|
||||
)
|
||||
connection.creation.create_test_db(
|
||||
verbosity=verbosity,
|
||||
autoclobber=not interactive,
|
||||
keepdb=keepdb,
|
||||
serialize=serialize_alias,
|
||||
serialize=connection.settings_dict['TEST'].get('SERIALIZE', True),
|
||||
)
|
||||
if parallel > 1:
|
||||
for index in range(parallel):
|
||||
@@ -233,15 +192,12 @@ def setup_databases(
|
||||
)
|
||||
# Configure all other connections as mirrors of the first one
|
||||
else:
|
||||
connections[alias].creation.set_as_test_mirror(
|
||||
connections[first_alias].settings_dict
|
||||
)
|
||||
connections[alias].creation.set_as_test_mirror(connections[first_alias].settings_dict)
|
||||
|
||||
# Configure the test mirrors.
|
||||
for alias, mirror_alias in mirrored_aliases.items():
|
||||
connections[alias].creation.set_as_test_mirror(
|
||||
connections[mirror_alias].settings_dict
|
||||
)
|
||||
connections[mirror_alias].settings_dict)
|
||||
|
||||
if debug_sql:
|
||||
for alias in connections:
|
||||
@@ -250,27 +206,6 @@ def setup_databases(
|
||||
return old_names
|
||||
|
||||
|
||||
def iter_test_cases(tests):
|
||||
"""
|
||||
Return an iterator over a test suite's unittest.TestCase objects.
|
||||
|
||||
The tests argument can also be an iterable of TestCase objects.
|
||||
"""
|
||||
for test in tests:
|
||||
if isinstance(test, str):
|
||||
# Prevent an unfriendly RecursionError that can happen with
|
||||
# strings.
|
||||
raise TypeError(
|
||||
f"Test {test!r} must be a test case or test suite not string "
|
||||
f"(was found in {tests!r})."
|
||||
)
|
||||
if isinstance(test, TestCase):
|
||||
yield test
|
||||
else:
|
||||
# Otherwise, assume it is a test suite.
|
||||
yield from iter_test_cases(test)
|
||||
|
||||
|
||||
def dependency_ordered(test_databases, dependencies):
|
||||
"""
|
||||
Reorder test_databases into an order that honors the dependencies
|
||||
@@ -334,18 +269,18 @@ def get_unique_databases_and_mirrors(aliases=None):
|
||||
|
||||
for alias in connections:
|
||||
connection = connections[alias]
|
||||
test_settings = connection.settings_dict["TEST"]
|
||||
test_settings = connection.settings_dict['TEST']
|
||||
|
||||
if test_settings["MIRROR"]:
|
||||
if test_settings['MIRROR']:
|
||||
# If the database is marked as a test mirror, save the alias.
|
||||
mirrored_aliases[alias] = test_settings["MIRROR"]
|
||||
mirrored_aliases[alias] = test_settings['MIRROR']
|
||||
elif alias in aliases:
|
||||
# Store a tuple with DB parameters that uniquely identify it.
|
||||
# If we have two aliases with the same values for that tuple,
|
||||
# we only need to create the test database once.
|
||||
item = test_databases.setdefault(
|
||||
connection.creation.test_db_signature(),
|
||||
(connection.settings_dict["NAME"], []),
|
||||
(connection.settings_dict['NAME'], []),
|
||||
)
|
||||
# The default database must be the first because data migrations
|
||||
# use the default alias by default.
|
||||
@@ -354,16 +289,11 @@ def get_unique_databases_and_mirrors(aliases=None):
|
||||
else:
|
||||
item[1].append(alias)
|
||||
|
||||
if "DEPENDENCIES" in test_settings:
|
||||
dependencies[alias] = test_settings["DEPENDENCIES"]
|
||||
if 'DEPENDENCIES' in test_settings:
|
||||
dependencies[alias] = test_settings['DEPENDENCIES']
|
||||
else:
|
||||
if (
|
||||
alias != DEFAULT_DB_ALIAS
|
||||
and connection.creation.test_db_signature() != default_sig
|
||||
):
|
||||
dependencies[alias] = test_settings.get(
|
||||
"DEPENDENCIES", [DEFAULT_DB_ALIAS]
|
||||
)
|
||||
if alias != DEFAULT_DB_ALIAS and connection.creation.test_db_signature() != default_sig:
|
||||
dependencies[alias] = test_settings.get('DEPENDENCIES', [DEFAULT_DB_ALIAS])
|
||||
|
||||
test_databases = dict(dependency_ordered(test_databases.items(), dependencies))
|
||||
return test_databases, mirrored_aliases
|
||||
@@ -385,12 +315,12 @@ def teardown_databases(old_config, verbosity, parallel=0, keepdb=False):
|
||||
|
||||
def get_runner(settings, test_runner_class=None):
|
||||
test_runner_class = test_runner_class or settings.TEST_RUNNER
|
||||
test_path = test_runner_class.split(".")
|
||||
test_path = test_runner_class.split('.')
|
||||
# Allow for relative paths
|
||||
if len(test_path) > 1:
|
||||
test_module_name = ".".join(test_path[:-1])
|
||||
test_module_name = '.'.join(test_path[:-1])
|
||||
else:
|
||||
test_module_name = "."
|
||||
test_module_name = '.'
|
||||
test_module = __import__(test_module_name, {}, {}, test_path[-1])
|
||||
return getattr(test_module, test_path[-1])
|
||||
|
||||
@@ -407,7 +337,6 @@ class TestContextDecorator:
|
||||
`kwarg_name`: keyword argument passing the return value of enable() if
|
||||
used as a function decorator.
|
||||
"""
|
||||
|
||||
def __init__(self, attr_name=None, kwarg_name=None):
|
||||
self.attr_name = attr_name
|
||||
self.kwarg_name = kwarg_name
|
||||
@@ -437,7 +366,7 @@ class TestContextDecorator:
|
||||
|
||||
cls.setUp = setUp
|
||||
return cls
|
||||
raise TypeError("Can only decorate subclasses of unittest.TestCase")
|
||||
raise TypeError('Can only decorate subclasses of unittest.TestCase')
|
||||
|
||||
def decorate_callable(self, func):
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
@@ -449,16 +378,13 @@ class TestContextDecorator:
|
||||
if self.kwarg_name:
|
||||
kwargs[self.kwarg_name] = context
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
else:
|
||||
|
||||
@wraps(func)
|
||||
def inner(*args, **kwargs):
|
||||
with self as context:
|
||||
if self.kwarg_name:
|
||||
kwargs[self.kwarg_name] = context
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return inner
|
||||
|
||||
def __call__(self, decorated):
|
||||
@@ -466,7 +392,7 @@ class TestContextDecorator:
|
||||
return self.decorate_class(decorated)
|
||||
elif callable(decorated):
|
||||
return self.decorate_callable(decorated)
|
||||
raise TypeError("Cannot decorate object of type %s" % type(decorated))
|
||||
raise TypeError('Cannot decorate object of type %s' % type(decorated))
|
||||
|
||||
|
||||
class override_settings(TestContextDecorator):
|
||||
@@ -476,7 +402,6 @@ class override_settings(TestContextDecorator):
|
||||
with the ``with`` statement. In either event, entering/exiting are called
|
||||
before and after, respectively, the function/block is executed.
|
||||
"""
|
||||
|
||||
enable_exception = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -486,9 +411,9 @@ class override_settings(TestContextDecorator):
|
||||
def enable(self):
|
||||
# Keep this code at the beginning to leave the settings unchanged
|
||||
# in case it raises an exception because INSTALLED_APPS is invalid.
|
||||
if "INSTALLED_APPS" in self.options:
|
||||
if 'INSTALLED_APPS' in self.options:
|
||||
try:
|
||||
apps.set_installed_apps(self.options["INSTALLED_APPS"])
|
||||
apps.set_installed_apps(self.options['INSTALLED_APPS'])
|
||||
except Exception:
|
||||
apps.unset_installed_apps()
|
||||
raise
|
||||
@@ -501,16 +426,14 @@ class override_settings(TestContextDecorator):
|
||||
try:
|
||||
setting_changed.send(
|
||||
sender=settings._wrapped.__class__,
|
||||
setting=key,
|
||||
value=new_value,
|
||||
enter=True,
|
||||
setting=key, value=new_value, enter=True,
|
||||
)
|
||||
except Exception as exc:
|
||||
self.enable_exception = exc
|
||||
self.disable()
|
||||
|
||||
def disable(self):
|
||||
if "INSTALLED_APPS" in self.options:
|
||||
if 'INSTALLED_APPS' in self.options:
|
||||
apps.unset_installed_apps()
|
||||
settings._wrapped = self.wrapped
|
||||
del self.wrapped
|
||||
@@ -519,9 +442,7 @@ class override_settings(TestContextDecorator):
|
||||
new_value = getattr(settings, key, None)
|
||||
responses_for_setting = setting_changed.send_robust(
|
||||
sender=settings._wrapped.__class__,
|
||||
setting=key,
|
||||
value=new_value,
|
||||
enter=False,
|
||||
setting=key, value=new_value, enter=False,
|
||||
)
|
||||
responses.extend(responses_for_setting)
|
||||
if self.enable_exception is not None:
|
||||
@@ -544,12 +465,10 @@ class override_settings(TestContextDecorator):
|
||||
|
||||
def decorate_class(self, cls):
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
if not issubclass(cls, SimpleTestCase):
|
||||
raise ValueError(
|
||||
"Only subclasses of Django SimpleTestCase can be decorated "
|
||||
"with override_settings"
|
||||
)
|
||||
"with override_settings")
|
||||
self.save_options(cls)
|
||||
return cls
|
||||
|
||||
@@ -559,7 +478,6 @@ class modify_settings(override_settings):
|
||||
Like override_settings, but makes it possible to append, prepend, or remove
|
||||
items instead of redefining the entire list.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if args:
|
||||
# Hack used when instantiating from SimpleTestCase.setUpClass.
|
||||
@@ -575,9 +493,8 @@ class modify_settings(override_settings):
|
||||
test_func._modified_settings = self.operations
|
||||
else:
|
||||
# Duplicate list to prevent subclasses from altering their parent.
|
||||
test_func._modified_settings = (
|
||||
list(test_func._modified_settings) + self.operations
|
||||
)
|
||||
test_func._modified_settings = list(
|
||||
test_func._modified_settings) + self.operations
|
||||
|
||||
def enable(self):
|
||||
self.options = {}
|
||||
@@ -592,11 +509,11 @@ class modify_settings(override_settings):
|
||||
# items my be a single value or an iterable.
|
||||
if isinstance(items, str):
|
||||
items = [items]
|
||||
if action == "append":
|
||||
if action == 'append':
|
||||
value = value + [item for item in items if item not in value]
|
||||
elif action == "prepend":
|
||||
elif action == 'prepend':
|
||||
value = [item for item in items if item not in value] + value
|
||||
elif action == "remove":
|
||||
elif action == 'remove':
|
||||
value = [item for item in value if item not in items]
|
||||
else:
|
||||
raise ValueError("Unsupported action: %s" % action)
|
||||
@@ -610,10 +527,8 @@ class override_system_checks(TestContextDecorator):
|
||||
Useful when you override `INSTALLED_APPS`, e.g. if you exclude `auth` app,
|
||||
you also need to exclude its system checks.
|
||||
"""
|
||||
|
||||
def __init__(self, new_checks, deployment_checks=None):
|
||||
from django.core.checks.registry import registry
|
||||
|
||||
self.registry = registry
|
||||
self.new_checks = new_checks
|
||||
self.deployment_checks = deployment_checks
|
||||
@@ -623,12 +538,12 @@ class override_system_checks(TestContextDecorator):
|
||||
self.old_checks = self.registry.registered_checks
|
||||
self.registry.registered_checks = set()
|
||||
for check in self.new_checks:
|
||||
self.registry.register(check, *getattr(check, "tags", ()))
|
||||
self.registry.register(check, *getattr(check, 'tags', ()))
|
||||
self.old_deployment_checks = self.registry.deployment_checks
|
||||
if self.deployment_checks is not None:
|
||||
self.registry.deployment_checks = set()
|
||||
for check in self.deployment_checks:
|
||||
self.registry.register(check, *getattr(check, "tags", ()), deploy=True)
|
||||
self.registry.register(check, *getattr(check, 'tags', ()), deploy=True)
|
||||
|
||||
def disable(self):
|
||||
self.registry.registered_checks = self.old_checks
|
||||
@@ -644,18 +559,18 @@ def compare_xml(want, got):
|
||||
|
||||
Based on https://github.com/lxml/lxml/blob/master/src/lxml/doctestcompare.py
|
||||
"""
|
||||
_norm_whitespace_re = re.compile(r"[ \t\n][ \t\n]+")
|
||||
_norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
|
||||
|
||||
def norm_whitespace(v):
|
||||
return _norm_whitespace_re.sub(" ", v)
|
||||
return _norm_whitespace_re.sub(' ', v)
|
||||
|
||||
def child_text(element):
|
||||
return "".join(
|
||||
c.data for c in element.childNodes if c.nodeType == Node.TEXT_NODE
|
||||
)
|
||||
return ''.join(c.data for c in element.childNodes
|
||||
if c.nodeType == Node.TEXT_NODE)
|
||||
|
||||
def children(element):
|
||||
return [c for c in element.childNodes if c.nodeType == Node.ELEMENT_NODE]
|
||||
return [c for c in element.childNodes
|
||||
if c.nodeType == Node.ELEMENT_NODE]
|
||||
|
||||
def norm_child_text(element):
|
||||
return norm_whitespace(child_text(element))
|
||||
@@ -674,9 +589,7 @@ def compare_xml(want, got):
|
||||
got_children = children(got_element)
|
||||
if len(want_children) != len(got_children):
|
||||
return False
|
||||
return all(
|
||||
check_element(want, got) for want, got in zip(want_children, got_children)
|
||||
)
|
||||
return all(check_element(want, got) for want, got in zip(want_children, got_children))
|
||||
|
||||
def first_node(document):
|
||||
for node in document.childNodes:
|
||||
@@ -687,13 +600,13 @@ def compare_xml(want, got):
|
||||
):
|
||||
return node
|
||||
|
||||
want = want.strip().replace("\\n", "\n")
|
||||
got = got.strip().replace("\\n", "\n")
|
||||
want = want.strip().replace('\\n', '\n')
|
||||
got = got.strip().replace('\\n', '\n')
|
||||
|
||||
# If the string is not a complete xml document, we may need to add a
|
||||
# root element. This allow us to compare fragments, like "<foo/><bar/>"
|
||||
if not want.startswith("<?xml"):
|
||||
wrapper = "<root>%s</root>"
|
||||
if not want.startswith('<?xml'):
|
||||
wrapper = '<root>%s</root>'
|
||||
want = wrapper % want
|
||||
got = wrapper % got
|
||||
|
||||
@@ -708,7 +621,6 @@ class CaptureQueriesContext:
|
||||
"""
|
||||
Context manager that captures queries executed by the specified connection.
|
||||
"""
|
||||
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
@@ -723,7 +635,7 @@ class CaptureQueriesContext:
|
||||
|
||||
@property
|
||||
def captured_queries(self):
|
||||
return self.connection.queries[self.initial_queries : self.final_queries]
|
||||
return self.connection.queries[self.initial_queries:self.final_queries]
|
||||
|
||||
def __enter__(self):
|
||||
self.force_debug_cursor = self.connection.force_debug_cursor
|
||||
@@ -747,7 +659,7 @@ class CaptureQueriesContext:
|
||||
class ignore_warnings(TestContextDecorator):
|
||||
def __init__(self, **kwargs):
|
||||
self.ignore_kwargs = kwargs
|
||||
if "message" in self.ignore_kwargs or "module" in self.ignore_kwargs:
|
||||
if 'message' in self.ignore_kwargs or 'module' in self.ignore_kwargs:
|
||||
self.filter_func = warnings.filterwarnings
|
||||
else:
|
||||
self.filter_func = warnings.simplefilter
|
||||
@@ -756,7 +668,7 @@ class ignore_warnings(TestContextDecorator):
|
||||
def enable(self):
|
||||
self.catch_warnings = warnings.catch_warnings()
|
||||
self.catch_warnings.__enter__()
|
||||
self.filter_func("ignore", **self.ignore_kwargs)
|
||||
self.filter_func('ignore', **self.ignore_kwargs)
|
||||
|
||||
def disable(self):
|
||||
self.catch_warnings.__exit__(*sys.exc_info())
|
||||
@@ -770,7 +682,7 @@ class ignore_warnings(TestContextDecorator):
|
||||
requires_tz_support = skipUnless(
|
||||
TZ_SUPPORT,
|
||||
"This test relies on the ability to run a program in an arbitrary "
|
||||
"time zone, but your operating system isn't able to do that.",
|
||||
"time zone, but your operating system isn't able to do that."
|
||||
)
|
||||
|
||||
|
||||
@@ -813,9 +725,9 @@ def captured_output(stream_name):
|
||||
def captured_stdout():
|
||||
"""Capture the output of sys.stdout:
|
||||
|
||||
with captured_stdout() as stdout:
|
||||
print("hello")
|
||||
self.assertEqual(stdout.getvalue(), "hello\n")
|
||||
with captured_stdout() as stdout:
|
||||
print("hello")
|
||||
self.assertEqual(stdout.getvalue(), "hello\n")
|
||||
"""
|
||||
return captured_output("stdout")
|
||||
|
||||
@@ -823,9 +735,9 @@ def captured_stdout():
|
||||
def captured_stderr():
|
||||
"""Capture the output of sys.stderr:
|
||||
|
||||
with captured_stderr() as stderr:
|
||||
print("hello", file=sys.stderr)
|
||||
self.assertEqual(stderr.getvalue(), "hello\n")
|
||||
with captured_stderr() as stderr:
|
||||
print("hello", file=sys.stderr)
|
||||
self.assertEqual(stderr.getvalue(), "hello\n")
|
||||
"""
|
||||
return captured_output("stderr")
|
||||
|
||||
@@ -833,12 +745,12 @@ def captured_stderr():
|
||||
def captured_stdin():
|
||||
"""Capture the input to sys.stdin:
|
||||
|
||||
with captured_stdin() as stdin:
|
||||
stdin.write('hello\n')
|
||||
stdin.seek(0)
|
||||
# call test code that consumes from sys.stdin
|
||||
captured = input()
|
||||
self.assertEqual(captured, "hello")
|
||||
with captured_stdin() as stdin:
|
||||
stdin.write('hello\n')
|
||||
stdin.seek(0)
|
||||
# call test code that consumes from sys.stdin
|
||||
captured = input()
|
||||
self.assertEqual(captured, "hello")
|
||||
"""
|
||||
return captured_output("stdin")
|
||||
|
||||
@@ -866,24 +778,18 @@ def require_jinja2(test_func):
|
||||
Django template engine for a test or skip it if Jinja2 isn't available.
|
||||
"""
|
||||
test_func = skipIf(jinja2 is None, "this test requires jinja2")(test_func)
|
||||
return override_settings(
|
||||
TEMPLATES=[
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"APP_DIRS": True,
|
||||
},
|
||||
{
|
||||
"BACKEND": "django.template.backends.jinja2.Jinja2",
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {"keep_trailing_newline": True},
|
||||
},
|
||||
]
|
||||
)(test_func)
|
||||
return override_settings(TEMPLATES=[{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'APP_DIRS': True,
|
||||
}, {
|
||||
'BACKEND': 'django.template.backends.jinja2.Jinja2',
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {'keep_trailing_newline': True},
|
||||
}])(test_func)
|
||||
|
||||
|
||||
class override_script_prefix(TestContextDecorator):
|
||||
"""Decorator or context manager to temporary override the script prefix."""
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
super().__init__()
|
||||
@@ -901,9 +807,8 @@ class LoggingCaptureMixin:
|
||||
Capture the output from the 'django' logger and store it on the class's
|
||||
logger_output attribute.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.logger = logging.getLogger("django")
|
||||
self.logger = logging.getLogger('django')
|
||||
self.old_stream = self.logger.handlers[0].stream
|
||||
self.logger_output = StringIO()
|
||||
self.logger.handlers[0].stream = self.logger_output
|
||||
@@ -928,7 +833,6 @@ class isolate_apps(TestContextDecorator):
|
||||
`kwarg_name`: keyword argument passing the isolated registry if used as a
|
||||
function decorator.
|
||||
"""
|
||||
|
||||
def __init__(self, *installed_apps, **kwargs):
|
||||
self.installed_apps = installed_apps
|
||||
super().__init__(**kwargs)
|
||||
@@ -936,11 +840,11 @@ class isolate_apps(TestContextDecorator):
|
||||
def enable(self):
|
||||
self.old_apps = Options.default_apps
|
||||
apps = Apps(self.installed_apps)
|
||||
setattr(Options, "default_apps", apps)
|
||||
setattr(Options, 'default_apps', apps)
|
||||
return apps
|
||||
|
||||
def disable(self):
|
||||
setattr(Options, "default_apps", self.old_apps)
|
||||
setattr(Options, 'default_apps', self.old_apps)
|
||||
|
||||
|
||||
class TimeKeeper:
|
||||
@@ -960,7 +864,7 @@ class TimeKeeper:
|
||||
def print_results(self):
|
||||
for name, end_times in self.records.items():
|
||||
for record_time in end_times:
|
||||
record = "%s took %.3fs" % (name, record_time)
|
||||
record = '%s took %.3fs' % (name, record_time)
|
||||
sys.stderr.write(record + os.linesep)
|
||||
|
||||
|
||||
@@ -975,14 +879,12 @@ class NullTimeKeeper:
|
||||
|
||||
def tag(*tags):
|
||||
"""Decorator to add tags to a test class or method."""
|
||||
|
||||
def decorator(obj):
|
||||
if hasattr(obj, "tags"):
|
||||
if hasattr(obj, 'tags'):
|
||||
obj.tags = obj.tags.union(tags)
|
||||
else:
|
||||
setattr(obj, "tags", set(tags))
|
||||
setattr(obj, 'tags', set(tags))
|
||||
return obj
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user