mirror of https://github.com/django/django.git
Fixed #31546 -- Allowed specifying list of tags in Command.requires_system_checks.
This commit is contained in:
parent
a4e6030904
commit
c60524c658
|
@ -12,7 +12,7 @@ UserModel = get_user_model()
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Change a user's password for django.contrib.auth."
|
help = "Change a user's password for django.contrib.auth."
|
||||||
requires_migrations_checks = True
|
requires_migrations_checks = True
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def _get_pass(self, prompt="Password: "):
|
def _get_pass(self, prompt="Password: "):
|
||||||
p = getpass.getpass(prompt=prompt)
|
p = getpass.getpass(prompt=prompt)
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Command(BaseCommand):
|
||||||
' ./manage.py ogrinspect zipcode.shp Zipcode'
|
' ./manage.py ogrinspect zipcode.shp Zipcode'
|
||||||
)
|
)
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('data_source', help='Path to the data source.')
|
parser.add_argument('data_source', help='Path to the data source.')
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Command(BaseCommand):
|
||||||
settings.STATIC_ROOT.
|
settings.STATIC_ROOT.
|
||||||
"""
|
"""
|
||||||
help = "Collect static files in a single location."
|
help = "Collect static files in a single location."
|
||||||
requires_system_checks = False
|
requires_system_checks = [Tags.staticfiles]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -36,10 +36,6 @@ class Command(BaseCommand):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
|
||||||
'--skip-checks', action='store_true',
|
|
||||||
help='Skip system checks.',
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--noinput', '--no-input', action='store_false', dest='interactive',
|
'--noinput', '--no-input', action='store_false', dest='interactive',
|
||||||
help="Do NOT prompt the user for input of any kind.",
|
help="Do NOT prompt the user for input of any kind.",
|
||||||
|
@ -151,9 +147,6 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
self.set_options(**options)
|
self.set_options(**options)
|
||||||
if not options['skip_checks']:
|
|
||||||
self.check(tags=[Tags.staticfiles])
|
|
||||||
|
|
||||||
message = ['\n']
|
message = ['\n']
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
message.append(
|
message.append(
|
||||||
|
|
|
@ -4,6 +4,7 @@ be executed through ``django-admin`` or ``manage.py``).
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
from argparse import ArgumentParser, HelpFormatter
|
from argparse import ArgumentParser, HelpFormatter
|
||||||
from io import TextIOBase
|
from io import TextIOBase
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ from django.core import checks
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.management.color import color_style, no_style
|
from django.core.management.color import color_style, no_style
|
||||||
from django.db import DEFAULT_DB_ALIAS, connections
|
from django.db import DEFAULT_DB_ALIAS, connections
|
||||||
|
from django.utils.deprecation import RemovedInDjango41Warning
|
||||||
|
|
||||||
|
ALL_CHECKS = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class CommandError(Exception):
|
class CommandError(Exception):
|
||||||
|
@ -203,8 +207,11 @@ class BaseCommand:
|
||||||
migrations on disk don't match the migrations in the database.
|
migrations on disk don't match the migrations in the database.
|
||||||
|
|
||||||
``requires_system_checks``
|
``requires_system_checks``
|
||||||
A boolean; if ``True``, entire Django project will be checked for errors
|
A list or tuple of tags, e.g. [Tags.staticfiles, Tags.models]. System
|
||||||
prior to executing the command. Default value is ``True``.
|
checks registered in the chosen tags will be checked for errors prior
|
||||||
|
to executing the command. The value '__all__' can be used to specify
|
||||||
|
that all system checks should be performed. Default value is '__all__'.
|
||||||
|
|
||||||
To validate an individual application's models
|
To validate an individual application's models
|
||||||
rather than all applications' models, call
|
rather than all applications' models, call
|
||||||
``self.check(app_configs)`` from ``handle()``, where ``app_configs``
|
``self.check(app_configs)`` from ``handle()``, where ``app_configs``
|
||||||
|
@ -222,7 +229,7 @@ class BaseCommand:
|
||||||
_called_from_command_line = False
|
_called_from_command_line = False
|
||||||
output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"
|
output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"
|
||||||
requires_migrations_checks = False
|
requires_migrations_checks = False
|
||||||
requires_system_checks = True
|
requires_system_checks = '__all__'
|
||||||
# Arguments, common to all commands, which aren't defined by the argument
|
# Arguments, common to all commands, which aren't defined by the argument
|
||||||
# parser.
|
# parser.
|
||||||
base_stealth_options = ('stderr', 'stdout')
|
base_stealth_options = ('stderr', 'stdout')
|
||||||
|
@ -239,6 +246,19 @@ class BaseCommand:
|
||||||
else:
|
else:
|
||||||
self.style = color_style(force_color)
|
self.style = color_style(force_color)
|
||||||
self.stderr.style_func = self.style.ERROR
|
self.stderr.style_func = self.style.ERROR
|
||||||
|
if self.requires_system_checks in [False, True]:
|
||||||
|
warnings.warn(
|
||||||
|
"Using a boolean value for requires_system_checks is "
|
||||||
|
"deprecated. Use '__all__' instead of True, and [] (an empty "
|
||||||
|
"list) instead of False.",
|
||||||
|
RemovedInDjango41Warning,
|
||||||
|
)
|
||||||
|
self.requires_system_checks = ALL_CHECKS if self.requires_system_checks else []
|
||||||
|
if (
|
||||||
|
not isinstance(self.requires_system_checks, (list, tuple)) and
|
||||||
|
self.requires_system_checks != ALL_CHECKS
|
||||||
|
):
|
||||||
|
raise TypeError('requires_system_checks must be a list or tuple.')
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
"""
|
"""
|
||||||
|
@ -365,7 +385,10 @@ class BaseCommand:
|
||||||
self.stderr = OutputWrapper(options['stderr'])
|
self.stderr = OutputWrapper(options['stderr'])
|
||||||
|
|
||||||
if self.requires_system_checks and not options['skip_checks']:
|
if self.requires_system_checks and not options['skip_checks']:
|
||||||
|
if self.requires_system_checks == ALL_CHECKS:
|
||||||
self.check()
|
self.check()
|
||||||
|
else:
|
||||||
|
self.check(tags=self.requires_system_checks)
|
||||||
if self.requires_migrations_checks:
|
if self.requires_migrations_checks:
|
||||||
self.check_migrations()
|
self.check_migrations()
|
||||||
output = self.handle(*args, **options)
|
output = self.handle(*args, **options)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.core.management.base import BaseCommand, CommandError
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Checks the entire Django project for potential problems."
|
help = "Checks the entire Django project for potential problems."
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('args', metavar='app_label', nargs='*')
|
parser.add_argument('args', metavar='app_label', nargs='*')
|
||||||
|
|
|
@ -29,7 +29,7 @@ def is_writable(path):
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Compiles .po files to .mo files for use with builtin gettext support.'
|
help = 'Compiles .po files to .mo files for use with builtin gettext support.'
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
program = 'msgfmt'
|
program = 'msgfmt'
|
||||||
program_options = ['--check-format']
|
program_options = ['--check-format']
|
||||||
|
|
|
@ -10,7 +10,7 @@ from django.db import (
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Creates the tables needed to use the SQL cache backend."
|
help = "Creates the tables needed to use the SQL cache backend."
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Command(BaseCommand):
|
||||||
"default database if none is provided."
|
"default database if none is provided."
|
||||||
)
|
)
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Command(BaseCommand):
|
||||||
help = """Displays differences between the current settings.py and Django's
|
help = """Displays differences between the current settings.py and Django's
|
||||||
default settings."""
|
default settings."""
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.db.models.constants import LOOKUP_SEP
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Introspects the database tables in the given database and outputs a Django model module."
|
help = "Introspects the database tables in the given database and outputs a Django model module."
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
stealth_options = ('table_name_filter',)
|
stealth_options = ('table_name_filter',)
|
||||||
db_module = 'django.db'
|
db_module = 'django.db'
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,7 @@ class Command(BaseCommand):
|
||||||
translatable_file_class = TranslatableFile
|
translatable_file_class = TranslatableFile
|
||||||
build_file_class = BuildFile
|
build_file_class = BuildFile
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
msgmerge_options = ['-q', '--previous']
|
msgmerge_options = ['-q', '--previous']
|
||||||
msguniq_options = ['--to-code=utf-8']
|
msguniq_options = ['--to-code=utf-8']
|
||||||
|
|
|
@ -20,7 +20,7 @@ from django.utils.text import Truncator
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Updates database schema. Manages both apps with migrations and those without."
|
help = "Updates database schema. Manages both apps with migrations and those without."
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Command(BaseCommand):
|
||||||
help = "Starts a lightweight Web server for development."
|
help = "Starts a lightweight Web server for development."
|
||||||
|
|
||||||
# Validation is called explicitly each time the server is reloaded.
|
# Validation is called explicitly each time the server is reloaded.
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
stealth_options = ('shutdown_message',)
|
stealth_options = ('shutdown_message',)
|
||||||
|
|
||||||
default_addr = '127.0.0.1'
|
default_addr = '127.0.0.1'
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Command(BaseCommand):
|
||||||
"as code."
|
"as code."
|
||||||
)
|
)
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
shells = ['ipython', 'bpython', 'python']
|
shells = ['ipython', 'bpython', 'python']
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Command(BaseCommand):
|
||||||
help = 'Discover and run tests in the specified modules or the current directory.'
|
help = 'Discover and run tests in the specified modules or the current directory.'
|
||||||
|
|
||||||
# DiscoverRunner runs the checks after databases are set up.
|
# DiscoverRunner runs the checks after databases are set up.
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
test_runner = None
|
test_runner = None
|
||||||
|
|
||||||
def run_from_argv(self, argv):
|
def run_from_argv(self, argv):
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.db import connection
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Runs a development server with data from the given fixture(s).'
|
help = 'Runs a development server with data from the given fixture(s).'
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
|
@ -28,7 +28,7 @@ class TemplateCommand(BaseCommand):
|
||||||
:param directory: The directory to which the template should be copied.
|
:param directory: The directory to which the template should be copied.
|
||||||
:param options: The additional variables passed to project or app templates
|
:param options: The additional variables passed to project or app templates
|
||||||
"""
|
"""
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
# The supported URL schemes
|
# The supported URL schemes
|
||||||
url_schemes = ['http', 'https', 'ftp']
|
url_schemes = ['http', 'https', 'ftp']
|
||||||
# Rewrite the following suffixes when determining the target filename.
|
# Rewrite the following suffixes when determining the target filename.
|
||||||
|
|
|
@ -215,8 +215,15 @@ All attributes can be set in your derived class and can be used in
|
||||||
|
|
||||||
.. attribute:: BaseCommand.requires_system_checks
|
.. attribute:: BaseCommand.requires_system_checks
|
||||||
|
|
||||||
A boolean; if ``True``, the entire Django project will be checked for
|
A list or tuple of tags, e.g. ``[Tags.staticfiles, Tags.models]``. System
|
||||||
potential problems prior to executing the command. Default value is ``True``.
|
checks registered in the chosen tags will be checked for errors prior to
|
||||||
|
executing the command. The value ``'__all__'`` can be used to specify
|
||||||
|
that all system checks should be performed. Default value is ``'__all__'``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
|
||||||
|
In older versions, the ``requires_system_checks`` attribute expects a
|
||||||
|
boolean value instead of a list or tuple of tags.
|
||||||
|
|
||||||
.. attribute:: BaseCommand.style
|
.. attribute:: BaseCommand.style
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ details on these changes.
|
||||||
``copy.deepcopy()`` to class attributes in ``TestCase.setUpTestData()`` will
|
``copy.deepcopy()`` to class attributes in ``TestCase.setUpTestData()`` will
|
||||||
be removed.
|
be removed.
|
||||||
|
|
||||||
|
* ``BaseCommand.requires_system_checks`` won't support boolean values.
|
||||||
|
|
||||||
.. _deprecation-removed-in-4.0:
|
.. _deprecation-removed-in-4.0:
|
||||||
|
|
||||||
4.0
|
4.0
|
||||||
|
|
|
@ -1826,7 +1826,7 @@ colored output to another command.
|
||||||
Skips running system checks prior to running the command. This option is only
|
Skips running system checks prior to running the command. This option is only
|
||||||
available if the
|
available if the
|
||||||
:attr:`~django.core.management.BaseCommand.requires_system_checks` command
|
:attr:`~django.core.management.BaseCommand.requires_system_checks` command
|
||||||
attribute is set to ``True``.
|
attribute is not an empty list or tuple.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,11 @@ Management Commands
|
||||||
connection. In that case, check for a consistent migration history is
|
connection. In that case, check for a consistent migration history is
|
||||||
skipped.
|
skipped.
|
||||||
|
|
||||||
|
* :attr:`.BaseCommand.requires_system_checks` now supports specifying a list of
|
||||||
|
tags. System checks registered in the chosen tags will be checked for errors
|
||||||
|
prior to executing the command. In previous versions, either all or none
|
||||||
|
of the system checks were performed.
|
||||||
|
|
||||||
Migrations
|
Migrations
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -273,3 +278,7 @@ Miscellaneous
|
||||||
* Assigning objects which don't support creating deep copies with
|
* Assigning objects which don't support creating deep copies with
|
||||||
:py:func:`copy.deepcopy` to class attributes in
|
:py:func:`copy.deepcopy` to class attributes in
|
||||||
:meth:`.TestCase.setUpTestData` is deprecated.
|
:meth:`.TestCase.setUpTestData` is deprecated.
|
||||||
|
|
||||||
|
* Using a boolean value in :attr:`.BaseCommand.requires_system_checks` is
|
||||||
|
deprecated. Use ``'__all__'`` instead of ``True``, and ``[]`` (an empty list)
|
||||||
|
instead of ``False``.
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.management.base import AppCommand
|
||||||
|
|
||||||
class Command(AppCommand):
|
class Command(AppCommand):
|
||||||
help = 'Test Application-based commands'
|
help = 'Test Application-based commands'
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle_app_config(self, app_config, **options):
|
def handle_app_config(self, app_config, **options):
|
||||||
print('EXECUTE:AppCommand name=%s, options=%s' % (app_config.name, sorted(options.items())))
|
print('EXECUTE:AppCommand name=%s, options=%s' % (app_config.name, sorted(options.items())))
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Test basic commands'
|
help = 'Test basic commands'
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('args', nargs='*')
|
parser.add_argument('args', nargs='*')
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.management.base import LabelCommand
|
||||||
|
|
||||||
class Command(LabelCommand):
|
class Command(LabelCommand):
|
||||||
help = "Test Label-based commands"
|
help = "Test Label-based commands"
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle_label(self, label, **options):
|
def handle_label(self, label, **options):
|
||||||
print('EXECUTE:LabelCommand label=%s, options=%s' % (label, sorted(options.items())))
|
print('EXECUTE:LabelCommand label=%s, options=%s' % (label, sorted(options.items())))
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Test No-args commands"
|
help = "Test No-args commands"
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
print('EXECUTE: noargs_command options=%s' % sorted(options.items()))
|
print('EXECUTE: noargs_command options=%s' % sorted(options.items()))
|
||||||
|
|
|
@ -1395,7 +1395,7 @@ class ManageTestserver(SimpleTestCase):
|
||||||
# the commands are correctly parsed and processed.
|
# the commands are correctly parsed and processed.
|
||||||
##########################################################################
|
##########################################################################
|
||||||
class ColorCommand(BaseCommand):
|
class ColorCommand(BaseCommand):
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
self.stdout.write('Hello, world!', self.style.ERROR)
|
self.stdout.write('Hello, world!', self.style.ERROR)
|
||||||
|
@ -1541,7 +1541,7 @@ class CommandTypes(AdminScriptTestCase):
|
||||||
|
|
||||||
def test_custom_stdout(self):
|
def test_custom_stdout(self):
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
self.stdout.write("Hello, World!")
|
self.stdout.write("Hello, World!")
|
||||||
|
@ -1558,7 +1558,7 @@ class CommandTypes(AdminScriptTestCase):
|
||||||
|
|
||||||
def test_custom_stderr(self):
|
def test_custom_stderr(self):
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
requires_system_checks = False
|
requires_system_checks = []
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
self.stderr.write("Hello, World!")
|
self.stderr.write("Hello, World!")
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.core.management.base import BaseCommand, CommandError
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Dance around like a madman."
|
help = "Dance around like a madman."
|
||||||
args = ''
|
args = ''
|
||||||
requires_system_checks = True
|
requires_system_checks = '__all__'
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument("integer", nargs='?', type=int, default=0)
|
parser.add_argument("integer", nargs='?', type=int, default=0)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
requires_system_checks = []
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
pass
|
|
@ -0,0 +1,9 @@
|
||||||
|
from django.core.checks import Tags
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
requires_system_checks = [Tags.staticfiles, Tags.models]
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
pass
|
|
@ -6,6 +6,7 @@ from admin_scripts.tests import AdminScriptTestCase
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.core import management
|
from django.core import management
|
||||||
|
from django.core.checks import Tags
|
||||||
from django.core.management import BaseCommand, CommandError, find_commands
|
from django.core.management import BaseCommand, CommandError, find_commands
|
||||||
from django.core.management.utils import (
|
from django.core.management.utils import (
|
||||||
find_command, get_random_secret_key, is_ignored_path,
|
find_command, get_random_secret_key, is_ignored_path,
|
||||||
|
@ -13,8 +14,9 @@ from django.core.management.utils import (
|
||||||
)
|
)
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.test import SimpleTestCase, override_settings
|
from django.test import SimpleTestCase, override_settings
|
||||||
from django.test.utils import captured_stderr, extend_sys_path
|
from django.test.utils import captured_stderr, extend_sys_path, ignore_warnings
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
from django.utils.deprecation import RemovedInDjango41Warning
|
||||||
from django.utils.version import PY37
|
from django.utils.version import PY37
|
||||||
|
|
||||||
from .management.commands import dance
|
from .management.commands import dance
|
||||||
|
@ -59,13 +61,13 @@ class CommandTests(SimpleTestCase):
|
||||||
with self.assertRaises(CommandError) as cm:
|
with self.assertRaises(CommandError) as cm:
|
||||||
management.call_command('dance', example="raise")
|
management.call_command('dance', example="raise")
|
||||||
self.assertEqual(cm.exception.returncode, 3)
|
self.assertEqual(cm.exception.returncode, 3)
|
||||||
dance.Command.requires_system_checks = False
|
dance.Command.requires_system_checks = []
|
||||||
try:
|
try:
|
||||||
with captured_stderr() as stderr, self.assertRaises(SystemExit) as cm:
|
with captured_stderr() as stderr, self.assertRaises(SystemExit) as cm:
|
||||||
management.ManagementUtility(['manage.py', 'dance', '--example=raise']).execute()
|
management.ManagementUtility(['manage.py', 'dance', '--example=raise']).execute()
|
||||||
self.assertEqual(cm.exception.code, 3)
|
self.assertEqual(cm.exception.code, 3)
|
||||||
finally:
|
finally:
|
||||||
dance.Command.requires_system_checks = True
|
dance.Command.requires_system_checks = '__all__'
|
||||||
self.assertIn("CommandError", stderr.getvalue())
|
self.assertIn("CommandError", stderr.getvalue())
|
||||||
|
|
||||||
def test_no_translations_deactivate_translations(self):
|
def test_no_translations_deactivate_translations(self):
|
||||||
|
@ -155,6 +157,7 @@ class CommandTests(SimpleTestCase):
|
||||||
|
|
||||||
def patched_check(self_, **kwargs):
|
def patched_check(self_, **kwargs):
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
saved_check = BaseCommand.check
|
saved_check = BaseCommand.check
|
||||||
BaseCommand.check = patched_check
|
BaseCommand.check = patched_check
|
||||||
|
@ -163,9 +166,28 @@ class CommandTests(SimpleTestCase):
|
||||||
self.assertEqual(self.counter, 0)
|
self.assertEqual(self.counter, 0)
|
||||||
management.call_command("dance", verbosity=0, skip_checks=False)
|
management.call_command("dance", verbosity=0, skip_checks=False)
|
||||||
self.assertEqual(self.counter, 1)
|
self.assertEqual(self.counter, 1)
|
||||||
|
self.assertEqual(self.kwargs, {})
|
||||||
finally:
|
finally:
|
||||||
BaseCommand.check = saved_check
|
BaseCommand.check = saved_check
|
||||||
|
|
||||||
|
def test_requires_system_checks_empty(self):
|
||||||
|
with mock.patch('django.core.management.base.BaseCommand.check') as mocked_check:
|
||||||
|
management.call_command('no_system_checks')
|
||||||
|
self.assertIs(mocked_check.called, False)
|
||||||
|
|
||||||
|
def test_requires_system_checks_specific(self):
|
||||||
|
with mock.patch('django.core.management.base.BaseCommand.check') as mocked_check:
|
||||||
|
management.call_command('specific_system_checks')
|
||||||
|
mocked_check.called_once_with(tags=[Tags.staticfiles, Tags.models])
|
||||||
|
|
||||||
|
def test_requires_system_checks_invalid(self):
|
||||||
|
class Command(BaseCommand):
|
||||||
|
requires_system_checks = 'x'
|
||||||
|
|
||||||
|
msg = 'requires_system_checks must be a list or tuple.'
|
||||||
|
with self.assertRaisesMessage(TypeError, msg):
|
||||||
|
Command()
|
||||||
|
|
||||||
def test_check_migrations(self):
|
def test_check_migrations(self):
|
||||||
requires_migrations_checks = dance.Command.requires_migrations_checks
|
requires_migrations_checks = dance.Command.requires_migrations_checks
|
||||||
self.assertIs(requires_migrations_checks, False)
|
self.assertIs(requires_migrations_checks, False)
|
||||||
|
@ -334,3 +356,45 @@ class UtilsTests(SimpleTestCase):
|
||||||
def test_normalize_path_patterns_truncates_wildcard_base(self):
|
def test_normalize_path_patterns_truncates_wildcard_base(self):
|
||||||
expected = [os.path.normcase(p) for p in ['foo/bar', 'bar/*/']]
|
expected = [os.path.normcase(p) for p in ['foo/bar', 'bar/*/']]
|
||||||
self.assertEqual(normalize_path_patterns(['foo/bar/*', 'bar/*/']), expected)
|
self.assertEqual(normalize_path_patterns(['foo/bar/*', 'bar/*/']), expected)
|
||||||
|
|
||||||
|
|
||||||
|
class DeprecationTests(SimpleTestCase):
|
||||||
|
def test_requires_system_checks_warning(self):
|
||||||
|
class Command(BaseCommand):
|
||||||
|
pass
|
||||||
|
|
||||||
|
msg = (
|
||||||
|
"Using a boolean value for requires_system_checks is deprecated. "
|
||||||
|
"Use '__all__' instead of True, and [] (an empty list) instead of "
|
||||||
|
"False."
|
||||||
|
)
|
||||||
|
for value in [False, True]:
|
||||||
|
Command.requires_system_checks = value
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango41Warning, msg):
|
||||||
|
Command()
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango41Warning)
|
||||||
|
def test_requires_system_checks_true(self):
|
||||||
|
class Command(BaseCommand):
|
||||||
|
requires_system_checks = True
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
pass
|
||||||
|
|
||||||
|
command = Command()
|
||||||
|
with mock.patch('django.core.management.base.BaseCommand.check') as mocked_check:
|
||||||
|
management.call_command(command, skip_checks=False)
|
||||||
|
mocked_check.assert_called_once_with()
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango41Warning)
|
||||||
|
def test_requires_system_checks_false(self):
|
||||||
|
class Command(BaseCommand):
|
||||||
|
requires_system_checks = False
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
pass
|
||||||
|
|
||||||
|
command = Command()
|
||||||
|
with mock.patch('django.core.management.base.BaseCommand.check') as mocked_check:
|
||||||
|
management.call_command(command)
|
||||||
|
self.assertIs(mocked_check.called, False)
|
||||||
|
|
Loading…
Reference in New Issue