mirror of https://github.com/django/django.git
Fixed #25264 -- Allowed suppressing base command options in --help output.
This also suppresses -verbosity and --trackback options in the runserver's help.
This commit is contained in:
parent
97f377cd35
commit
b667ac24ea
|
@ -2,6 +2,7 @@
|
||||||
Base classes for writing management commands (named commands which can
|
Base classes for writing management commands (named commands which can
|
||||||
be executed through ``django-admin`` or ``manage.py``).
|
be executed through ``django-admin`` or ``manage.py``).
|
||||||
"""
|
"""
|
||||||
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -239,6 +240,7 @@ class BaseCommand:
|
||||||
base_stealth_options = ('stderr', 'stdout')
|
base_stealth_options = ('stderr', 'stdout')
|
||||||
# Command-specific options not defined by the argument parser.
|
# Command-specific options not defined by the argument parser.
|
||||||
stealth_options = ()
|
stealth_options = ()
|
||||||
|
suppressed_base_arguments = set()
|
||||||
|
|
||||||
def __init__(self, stdout=None, stderr=None, no_color=False, force_color=False):
|
def __init__(self, stdout=None, stderr=None, no_color=False, force_color=False):
|
||||||
self.stdout = OutputWrapper(stdout or sys.stdout)
|
self.stdout = OutputWrapper(stdout or sys.stdout)
|
||||||
|
@ -285,31 +287,37 @@ class BaseCommand:
|
||||||
called_from_command_line=getattr(self, '_called_from_command_line', None),
|
called_from_command_line=getattr(self, '_called_from_command_line', None),
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
parser.add_argument('--version', action='version', version=self.get_version())
|
self.add_base_argument(
|
||||||
parser.add_argument(
|
parser, '--version', action='version', version=self.get_version(),
|
||||||
'-v', '--verbosity', default=1,
|
help="Show program's version number and exit.",
|
||||||
|
)
|
||||||
|
self.add_base_argument(
|
||||||
|
parser, '-v', '--verbosity', default=1,
|
||||||
type=int, choices=[0, 1, 2, 3],
|
type=int, choices=[0, 1, 2, 3],
|
||||||
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output',
|
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output',
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
self.add_base_argument(
|
||||||
'--settings',
|
parser, '--settings',
|
||||||
help=(
|
help=(
|
||||||
'The Python path to a settings module, e.g. '
|
'The Python path to a settings module, e.g. '
|
||||||
'"myproject.settings.main". If this isn\'t provided, the '
|
'"myproject.settings.main". If this isn\'t provided, the '
|
||||||
'DJANGO_SETTINGS_MODULE environment variable will be used.'
|
'DJANGO_SETTINGS_MODULE environment variable will be used.'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
self.add_base_argument(
|
||||||
'--pythonpath',
|
parser, '--pythonpath',
|
||||||
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".',
|
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".',
|
||||||
)
|
)
|
||||||
parser.add_argument('--traceback', action='store_true', help='Raise on CommandError exceptions')
|
self.add_base_argument(
|
||||||
parser.add_argument(
|
parser, '--traceback', action='store_true',
|
||||||
'--no-color', action='store_true',
|
help='Raise on CommandError exceptions.',
|
||||||
|
)
|
||||||
|
self.add_base_argument(
|
||||||
|
parser, '--no-color', action='store_true',
|
||||||
help="Don't colorize the command output.",
|
help="Don't colorize the command output.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
self.add_base_argument(
|
||||||
'--force-color', action='store_true',
|
parser, '--force-color', action='store_true',
|
||||||
help='Force colorization of the command output.',
|
help='Force colorization of the command output.',
|
||||||
)
|
)
|
||||||
if self.requires_system_checks:
|
if self.requires_system_checks:
|
||||||
|
@ -326,6 +334,17 @@ class BaseCommand:
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_base_argument(self, parser, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Call the parser's add_argument() method, suppressing the help text
|
||||||
|
according to BaseCommand.suppressed_base_arguments.
|
||||||
|
"""
|
||||||
|
for arg in args:
|
||||||
|
if arg in self.suppressed_base_arguments:
|
||||||
|
kwargs['help'] = argparse.SUPPRESS
|
||||||
|
break
|
||||||
|
parser.add_argument(*args, **kwargs)
|
||||||
|
|
||||||
def print_help(self, prog_name, subcommand):
|
def print_help(self, prog_name, subcommand):
|
||||||
"""
|
"""
|
||||||
Print the help message for this command, derived from
|
Print the help message for this command, derived from
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Command(BaseCommand):
|
||||||
# Validation is called explicitly each time the server is reloaded.
|
# Validation is called explicitly each time the server is reloaded.
|
||||||
requires_system_checks = []
|
requires_system_checks = []
|
||||||
stealth_options = ('shutdown_message',)
|
stealth_options = ('shutdown_message',)
|
||||||
|
suppressed_base_arguments = {'--verbosity', '--traceback'}
|
||||||
|
|
||||||
default_addr = '127.0.0.1'
|
default_addr = '127.0.0.1'
|
||||||
default_addr_ipv6 = '::1'
|
default_addr_ipv6 = '::1'
|
||||||
|
|
|
@ -242,6 +242,14 @@ All attributes can be set in your derived class and can be used in
|
||||||
If you pass the :option:`--no-color` option when running your command, all
|
If you pass the :option:`--no-color` option when running your command, all
|
||||||
``self.style()`` calls will return the original string uncolored.
|
``self.style()`` calls will return the original string uncolored.
|
||||||
|
|
||||||
|
.. attribute:: BaseCommand.suppressed_base_arguments
|
||||||
|
|
||||||
|
.. versionadded:: 4.0
|
||||||
|
|
||||||
|
The default command options to suppress in the help output. This should be
|
||||||
|
a set of option names (e.g. ``'--verbosity'``). The default values for the
|
||||||
|
suppressed options are still passed.
|
||||||
|
|
||||||
Methods
|
Methods
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,10 @@ Management Commands
|
||||||
As a consequence, ``readline`` is no longer loaded if running in *isolated*
|
As a consequence, ``readline`` is no longer loaded if running in *isolated*
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
|
* The new :attr:`BaseCommand.suppressed_base_arguments
|
||||||
|
<django.core.management.BaseCommand.suppressed_base_arguments>` attribute
|
||||||
|
allows suppressing unsupported default command options in the help output.
|
||||||
|
|
||||||
Migrations
|
Migrations
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
from django.core.management import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
help = 'Test suppress base options command.'
|
||||||
|
requires_system_checks = []
|
||||||
|
suppressed_base_arguments = {
|
||||||
|
'-v',
|
||||||
|
'--traceback',
|
||||||
|
'--settings',
|
||||||
|
'--pythonpath',
|
||||||
|
'--no-color',
|
||||||
|
'--force-color',
|
||||||
|
'--version',
|
||||||
|
'file',
|
||||||
|
}
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
super().add_arguments(parser)
|
||||||
|
self.add_base_argument(parser, 'file', nargs='?', help='input file')
|
||||||
|
|
||||||
|
def handle(self, *labels, **options):
|
||||||
|
print('EXECUTE:SuppressBaseOptionsCommand options=%s' % sorted(options.items()))
|
|
@ -1381,6 +1381,15 @@ class ManageRunserverEmptyAllowedHosts(AdminScriptTestCase):
|
||||||
self.assertOutput(err, 'CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.')
|
self.assertOutput(err, 'CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.')
|
||||||
|
|
||||||
|
|
||||||
|
class ManageRunserverHelpOutput(AdminScriptTestCase):
|
||||||
|
def test_suppressed_options(self):
|
||||||
|
"""runserver doesn't support --verbosity and --trackback options."""
|
||||||
|
out, err = self.run_manage(['runserver', '--help'])
|
||||||
|
self.assertNotInOutput(out, '--verbosity')
|
||||||
|
self.assertNotInOutput(out, '--trackback')
|
||||||
|
self.assertOutput(out, '--settings')
|
||||||
|
|
||||||
|
|
||||||
class ManageTestserver(SimpleTestCase):
|
class ManageTestserver(SimpleTestCase):
|
||||||
|
|
||||||
@mock.patch.object(TestserverCommand, 'handle', return_value='')
|
@mock.patch.object(TestserverCommand, 'handle', return_value='')
|
||||||
|
@ -1847,6 +1856,34 @@ class CommandTypes(AdminScriptTestCase):
|
||||||
"('settings', None), ('traceback', False), ('verbosity', 1)]"
|
"('settings', None), ('traceback', False), ('verbosity', 1)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_suppress_base_options_command_help(self):
|
||||||
|
args = ['suppress_base_options_command', '--help']
|
||||||
|
out, err = self.run_manage(args)
|
||||||
|
self.assertNoOutput(err)
|
||||||
|
self.assertOutput(out, 'Test suppress base options command.')
|
||||||
|
self.assertNotInOutput(out, 'input file')
|
||||||
|
self.assertOutput(out, '-h, --help')
|
||||||
|
self.assertNotInOutput(out, '--version')
|
||||||
|
self.assertNotInOutput(out, '--verbosity')
|
||||||
|
self.assertNotInOutput(out, '-v {0,1,2,3}')
|
||||||
|
self.assertNotInOutput(out, '--settings')
|
||||||
|
self.assertNotInOutput(out, '--pythonpath')
|
||||||
|
self.assertNotInOutput(out, '--traceback')
|
||||||
|
self.assertNotInOutput(out, '--no-color')
|
||||||
|
self.assertNotInOutput(out, '--force-color')
|
||||||
|
|
||||||
|
def test_suppress_base_options_command_defaults(self):
|
||||||
|
args = ['suppress_base_options_command']
|
||||||
|
out, err = self.run_manage(args)
|
||||||
|
self.assertNoOutput(err)
|
||||||
|
self.assertOutput(
|
||||||
|
out,
|
||||||
|
"EXECUTE:SuppressBaseOptionsCommand options=[('file', None), "
|
||||||
|
"('force_color', False), ('no_color', False), "
|
||||||
|
"('pythonpath', None), ('settings', None), "
|
||||||
|
"('traceback', False), ('verbosity', 1)]"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Discovery(SimpleTestCase):
|
class Discovery(SimpleTestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue