Refs #26315 -- Cleaned up argparse options in commands.

* Removed type coercion. Options created by argparse are already coerced
  to the correct type.
* Removed fallback default values. Options created by argparse already
  have a default value.
* Used direct indexing. Options created by argparse are always set. This
  eliminates the need to use dict.get().
This commit is contained in:
Jon Dufresne 2016-03-02 18:01:36 -08:00 committed by Tim Graham
parent 4115288b4f
commit 1845bc1d10
21 changed files with 87 additions and 78 deletions

View File

@ -29,7 +29,7 @@ class Command(BaseCommand):
help='Specifies the database to use. Default is "default".')
def handle(self, *args, **options):
if options.get('username'):
if options['username']:
username = options['username']
else:
username = getpass.getuser()
@ -37,7 +37,7 @@ class Command(BaseCommand):
UserModel = get_user_model()
try:
u = UserModel._default_manager.using(options.get('database')).get(**{
u = UserModel._default_manager.using(options['database']).get(**{
UserModel.USERNAME_FIELD: username
})
except UserModel.DoesNotExist:

View File

@ -53,8 +53,8 @@ class Command(BaseCommand):
return super(Command, self).execute(*args, **options)
def handle(self, *args, **options):
username = options.get(self.UserModel.USERNAME_FIELD)
database = options.get('database')
username = options[self.UserModel.USERNAME_FIELD]
database = options['database']
# If not provided, create the user with an unusable password
password = None
@ -72,7 +72,7 @@ class Command(BaseCommand):
username = self.username_field.clean(username, None)
for field_name in self.UserModel.REQUIRED_FIELDS:
if options.get(field_name):
if options[field_name]:
field = self.UserModel._meta.get_field(field_name)
user_data[field_name] = field.clean(options[field_name], None)
else:
@ -118,7 +118,7 @@ class Command(BaseCommand):
for field_name in self.UserModel.REQUIRED_FIELDS:
field = self.UserModel._meta.get_field(field_name)
user_data[field_name] = options.get(field_name)
user_data[field_name] = options[field_name]
while user_data[field_name] is None:
message = force_str('%s%s: ' % (
capfirst(field.verbose_name),

View File

@ -21,8 +21,8 @@ class Command(RunserverCommand):
handler.
"""
handler = super(Command, self).get_handler(*args, **options)
use_static_handler = options.get('use_static_handler', True)
insecure_serving = options.get('insecure_serving', False)
use_static_handler = options['use_static_handler']
insecure_serving = options['insecure_serving']
if use_static_handler and (settings.DEBUG or insecure_serving):
return StaticFilesHandler(handler)
return handler

View File

@ -314,13 +314,13 @@ class BaseCommand(object):
controlled by the ``requires_system_checks`` attribute, except if
force-skipped).
"""
if options.get('no_color'):
if options['no_color']:
self.style = no_style()
self.stderr.style_func = None
if options.get('stdout'):
self.stdout = OutputWrapper(options['stdout'])
if options.get('stderr'):
self.stderr = OutputWrapper(options.get('stderr'), self.stderr.style_func)
self.stderr = OutputWrapper(options['stderr'], self.stderr.style_func)
saved_locale = None
if not self.leave_locale_alone:

View File

@ -33,7 +33,7 @@ class Command(BaseCommand):
def handle(self, *app_labels, **options):
include_deployment_checks = options['deploy']
if options.get('list_tags'):
if options['list_tags']:
self.stdout.write('\n'.join(sorted(registry.tags_available(include_deployment_checks))))
return
@ -42,7 +42,7 @@ class Command(BaseCommand):
else:
app_configs = None
tags = options.get('tags')
tags = options['tags']
if tags:
try:
invalid_tag = next(

View File

@ -45,10 +45,10 @@ class Command(BaseCommand):
help='Use fuzzy translations.')
def handle(self, **options):
locale = options.get('locale')
exclude = options.get('exclude')
self.verbosity = int(options.get('verbosity'))
if options.get('fuzzy'):
locale = options['locale']
exclude = options['exclude']
self.verbosity = options['verbosity']
if options['fuzzy']:
self.program_options = self.program_options + ['-f']
if find_command(self.program) is None:

View File

@ -27,9 +27,9 @@ class Command(BaseCommand):
'be run.')
def handle(self, *tablenames, **options):
db = options.get('database')
self.verbosity = int(options.get('verbosity'))
dry_run = options.get('dry_run')
db = options['database']
self.verbosity = options['verbosity']
dry_run = options['dry_run']
if len(tablenames):
# Legacy behavior, tablename specified as argument
for tablename in tablenames:

View File

@ -14,7 +14,7 @@ class Command(BaseCommand):
'open a shell. Defaults to the "default" database.')
def handle(self, **options):
connection = connections[options.get('database')]
connection = connections[options['database']]
try:
connection.client.runshell()
except OSError:

View File

@ -45,16 +45,16 @@ class Command(BaseCommand):
help='Specifies file to which the output is written.')
def handle(self, *app_labels, **options):
format = options.get('format')
indent = options.get('indent')
using = options.get('database')
excludes = options.get('exclude')
output = options.get('output')
show_traceback = options.get('traceback')
use_natural_foreign_keys = options.get('use_natural_foreign_keys')
use_natural_primary_keys = options.get('use_natural_primary_keys')
use_base_manager = options.get('use_base_manager')
pks = options.get('primary_keys')
format = options['format']
indent = options['indent']
using = options['database']
excludes = options['exclude']
output = options['output']
show_traceback = options['traceback']
use_natural_foreign_keys = options['use_natural_foreign_keys']
use_natural_primary_keys = options['use_natural_primary_keys']
use_base_manager = options['use_base_manager']
pks = options['primary_keys']
if pks:
primary_keys = pks.split(',')

View File

@ -25,10 +25,10 @@ class Command(BaseCommand):
help='Nominates a database to flush. Defaults to the "default" database.')
def handle(self, **options):
database = options.get('database')
database = options['database']
connection = connections[database]
verbosity = options.get('verbosity')
interactive = options.get('interactive')
verbosity = options['verbosity']
interactive = options['interactive']
# The following are stealth options used by Django's internals.
reset_sequences = options.get('reset_sequences', True)
allow_cascade = options.get('allow_cascade', False)

View File

@ -50,10 +50,10 @@ class Command(BaseCommand):
def handle(self, *fixture_labels, **options):
self.ignore = options.get('ignore')
self.using = options.get('database')
self.app_label = options.get('app_label')
self.verbosity = options.get('verbosity')
self.ignore = options['ignore']
self.using = options['database']
self.app_label = options['app_label']
self.verbosity = options['verbosity']
with transaction.atomic(using=self.using):
self.loaddata(fixture_labels)

View File

@ -212,13 +212,13 @@ class Command(BaseCommand):
default=False, help="Keep .pot file after making messages. Useful when debugging.")
def handle(self, *args, **options):
locale = options.get('locale')
exclude = options.get('exclude')
self.domain = options.get('domain')
self.verbosity = options.get('verbosity')
process_all = options.get('all')
extensions = options.get('extensions')
self.symlinks = options.get('symlinks')
locale = options['locale']
exclude = options['exclude']
self.domain = options['domain']
self.verbosity = options['verbosity']
process_all = options['all']
extensions = options['extensions']
self.symlinks = options['symlinks']
# Need to ensure that the i18n framework is enabled
if settings.configured:
@ -226,25 +226,25 @@ class Command(BaseCommand):
else:
settings.configure(USE_I18N=True)
ignore_patterns = options.get('ignore_patterns')
if options.get('use_default_ignore_patterns'):
ignore_patterns = options['ignore_patterns']
if options['use_default_ignore_patterns']:
ignore_patterns += ['CVS', '.*', '*~', '*.pyc']
self.ignore_patterns = list(set(ignore_patterns))
# Avoid messing with mutable class variables
if options.get('no_wrap'):
if options['no_wrap']:
self.msgmerge_options = self.msgmerge_options[:] + ['--no-wrap']
self.msguniq_options = self.msguniq_options[:] + ['--no-wrap']
self.msgattrib_options = self.msgattrib_options[:] + ['--no-wrap']
self.xgettext_options = self.xgettext_options[:] + ['--no-wrap']
if options.get('no_location'):
if options['no_location']:
self.msgmerge_options = self.msgmerge_options[:] + ['--no-location']
self.msguniq_options = self.msguniq_options[:] + ['--no-location']
self.msgattrib_options = self.msgattrib_options[:] + ['--no-location']
self.xgettext_options = self.xgettext_options[:] + ['--no-location']
self.no_obsolete = options.get('no_obsolete')
self.keep_pot = options.get('keep_pot')
self.no_obsolete = options['no_obsolete']
self.keep_pot = options['keep_pot']
if self.domain not in ('django', 'djangojs'):
raise CommandError("currently makemessages only supports domains "

View File

@ -43,13 +43,13 @@ class Command(BaseCommand):
help='Exit with a non-zero status if model changes are missing migrations.')
def handle(self, *app_labels, **options):
self.verbosity = options.get('verbosity')
self.interactive = options.get('interactive')
self.dry_run = options.get('dry_run', False)
self.merge = options.get('merge', False)
self.empty = options.get('empty', False)
self.migration_name = options.get('name')
self.exit_code = options.get('exit_code', False)
self.verbosity = options['verbosity']
self.interactive = options['interactive']
self.dry_run = options['dry_run']
self.merge = options['merge']
self.empty = options['empty']
self.migration_name = options['name']
self.exit_code = options['exit_code']
check_changes = options['check_changes']
if self.exit_code:

View File

@ -47,8 +47,8 @@ class Command(BaseCommand):
def handle(self, *args, **options):
self.verbosity = options.get('verbosity')
self.interactive = options.get('interactive')
self.verbosity = options['verbosity']
self.interactive = options['interactive']
# Import the 'management' module within each installed app, to register
# dispatcher events.
@ -57,7 +57,7 @@ class Command(BaseCommand):
import_module('.management', app_config.name)
# Get the database we're operating from
db = options.get('database')
db = options['database']
connection = connections[db]
# Hook for backends needing any database preparation
@ -114,7 +114,7 @@ class Command(BaseCommand):
targets = executor.loader.graph.leaf_nodes()
plan = executor.migration_plan(targets)
run_syncdb = options.get('run_syncdb') and executor.loader.unmigrated_apps
run_syncdb = options['run_syncdb'] and executor.loader.unmigrated_apps
# Print some useful info
if self.verbosity >= 1:
@ -172,8 +172,8 @@ class Command(BaseCommand):
"apply them."
))
else:
fake = options.get("fake")
fake_initial = options.get("fake_initial")
fake = options['fake']
fake_initial = options['fake_initial']
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
# Send the post_migrate signal, so individual apps can do whatever they need

View File

@ -42,7 +42,7 @@ class Command(BaseCommand):
help='Tells Django to NOT use the auto-reloader.')
def execute(self, *args, **options):
if options.get('no_color'):
if options['no_color']:
# We rely on the environment because it's currently the only
# way to reach WSGIRequestHandler. This seems an acceptable
# compromise considering `runserver` runs indefinitely.
@ -61,11 +61,11 @@ class Command(BaseCommand):
if not settings.DEBUG and not settings.ALLOWED_HOSTS:
raise CommandError('You must set settings.ALLOWED_HOSTS if DEBUG is False.')
self.use_ipv6 = options.get('use_ipv6')
self.use_ipv6 = options['use_ipv6']
if self.use_ipv6 and not socket.has_ipv6:
raise CommandError('Your Python does not support IPv6.')
self._raw_ipv6 = False
if not options.get('addrport'):
if not options['addrport']:
self.addr = ''
self.port = self.default_port
else:
@ -85,14 +85,14 @@ class Command(BaseCommand):
raise CommandError('"%s" is not a valid IPv6 address.' % self.addr)
if not self.addr:
self.addr = '::1' if self.use_ipv6 else '127.0.0.1'
self._raw_ipv6 = bool(self.use_ipv6)
self._raw_ipv6 = self.use_ipv6
self.run(**options)
def run(self, **options):
"""
Runs the server, using the autoreloader if needed
"""
use_reloader = options.get('use_reloader')
use_reloader = options['use_reloader']
if use_reloader:
autoreload.main(self.inner_run, None, options)
@ -104,7 +104,8 @@ class Command(BaseCommand):
# to be raised in the child process, raise it now.
autoreload.raise_last_exception()
threading = options.get('use_threading')
threading = options['use_threading']
# 'shutdown_message' is a stealth option.
shutdown_message = options.get('shutdown_message', '')
quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C'

View File

@ -24,10 +24,10 @@ class Command(BaseCommand):
parser.set_defaults(format='list')
def handle(self, *args, **options):
self.verbosity = options.get('verbosity')
self.verbosity = options['verbosity']
# Get the database we're operating from
db = options.get('database')
db = options['database']
connection = connections[db]
if options['format'] == "plan":

View File

@ -18,7 +18,7 @@ class Command(AppCommand):
def handle_app_config(self, app_config, **options):
if app_config.models_module is None:
return
connection = connections[options.get('database')]
connection = connections[options['database']]
models = app_config.get_models(include_auto_created=True)
statements = connection.ops.sequence_reset_sql(self.style, models)
return '\n'.join(statements)

View File

@ -27,8 +27,8 @@ class Command(BaseCommand):
def handle(self, **options):
self.verbosity = options.get('verbosity')
self.interactive = options.get('interactive')
self.verbosity = options['verbosity']
self.interactive = options['interactive']
app_label = options['app_label']
start_migration_name = options['start_migration_name']
migration_name = options['migration_name']

View File

@ -57,9 +57,9 @@ class Command(BaseCommand):
from django.conf import settings
from django.test.utils import get_runner
TestRunner = get_runner(settings, options.get('testrunner'))
TestRunner = get_runner(settings, options['testrunner'])
if options.get('liveserver') is not None:
if options['liveserver'] is not None:
os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = options['liveserver']
del options['liveserver']

View File

@ -20,8 +20,8 @@ class Command(BaseCommand):
help='Tells Django to use an IPv6 address.')
def handle(self, *fixture_labels, **options):
verbosity = options.get('verbosity')
interactive = options.get('interactive')
verbosity = options['verbosity']
interactive = options['interactive']
# Create a test database.
db_name = connection.creation.create_test_db(verbosity=verbosity, autoclobber=not interactive, serialize=False)

View File

@ -640,6 +640,14 @@ Miscellaneous
* Tests that violate deferrable database constraints will now error when run on
a database that supports deferrable constraints.
* Built-in management commands now use indexing of keys in ``options``, e.g.
``options['verbosity']``, instead of ``options.get()`` and no longer perform
any type coercion. This could be a problem if you're calling commands using
``Command.execute()`` (which bypasses the argument parser that sets a default
value) instead of :func:`~django.core.management.call_command`. Instead of
calling ``Command.execute()``, pass the command object as the first argument
to ``call_command()``.
.. _deprecated-features-1.10:
Features deprecated in 1.10