Skip to content

Commit

Permalink
Only add 'args' argument once to command parser.
Browse files Browse the repository at this point in the history
If a custom management LabelCommand or AppCommand uses 'args' then only
the last positional argument provided is passed to the command, because
argparse's behaviour when two calls to add_argument with the same name
is undefined (it appears to put all the arguments bar one in the first
'*' argument, then the last one in the '+' argument).

This shows this with a test, and fixes it by not making the first call
to parser.add_argument('args') if it's a LabelCommand or AppCommand.
  • Loading branch information
dracos committed Jan 31, 2017
1 parent b248f33 commit fedc38a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 1 deletion.
2 changes: 1 addition & 1 deletion django/core/management/base.py
Expand Up @@ -349,7 +349,7 @@ def store_as_int(option, opt_str, value, parser):
help='Raise on CommandError exceptions')
parser.add_argument('--no-color', action='store_true', dest='no_color', default=False,
help="Don't colorize the command output.")
if self.args:
if self.args and not isinstance(self, LabelCommand) and not isinstance(self, AppCommand):
# Keep compatibility and always accept positional arguments, like optparse when args is set
parser.add_argument('args', nargs='*')
self.add_arguments(parser)
Expand Down
8 changes: 8 additions & 0 deletions tests/admin_scripts/tests.py
Expand Up @@ -1683,6 +1683,14 @@ def test_label_command_multiple_label(self):
self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]")
self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]")

def test_label_command_with_args_multiple_label(self):
"User LabelCommands using 'args' are executed multiple times if multiple labels are provided"
args = ['label_command_with_args', 'testlabel', 'anotherlabel']
out, err = self.run_manage(args)
self.assertNoOutput(err)
self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]")
self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', False), ('verbosity', 1)]")

@ignore_warnings(category=RemovedInDjango19Warning)
def test_requires_model_validation_and_requires_system_checks_both_defined(self):
from .management.commands.validation_command import InvalidCommand
Expand Down

0 comments on commit fedc38a

Please sign in to comment.