#33041 closed Bug (invalid)
call_command() returns different values for options than manage.py when nargs is specified.
Reported by: | Kevin Follstad | Owned by: | nobody |
---|---|---|---|
Component: | Core (Management commands) | Version: | 3.1 |
Severity: | Normal | Keywords: | call_command nargs |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Maybe I am not understanding something in the documentation, but this seems like a bug (tested on 3.1.7).
When nargs is specified for an option, according to the argparse documentation, the parsed option should always be a list containing the option's values. However that is not the case if options are specified as kw="the-kw-option" when passed to call_command. For example:
main/test/management/commands/commandbug.py:
from django.core.management.base import BaseCommand from django.core.management import call_command # Broken: kw is not a list def call_commandbug1(): call_command("commandbug", "the-positional-arg", kw="the-kw-arg") # Works: kw is a list def call_commandbug2(): call_command("commandbug", "the-positional-arg", "--kw=the-kw-arg") class Command(BaseCommand): help = "Minimal call_command bug demo" def add_arguments(self, parser): parser.add_argument( "positional", nargs=1, type=str, help="Positional arg" ) parser.add_argument( "--kw", nargs=1, type=str, help="Keyword arg", ) super().add_arguments(parser) def handle(self, *args, **options): print(options)
When run from call_command1 the value of kw is not a list:
$> ./manage.py shell Python 3.9.6 (default, Jun 30 2021, 10:22:16) In [1]: from main.test.management.commands.commandbug import call_commandbug1, call_commandbug2 In [2]: call_commandbug1() {'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'skip_checks': True, 'positional': ['the-positional-arg'], 'kw': 'the-kw-arg'}
When run from call_command2, the value is kw is a list matching argparse:
In [3]: call_commandbug2() {'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'skip_checks': True, 'positional': ['the-positional-arg'], 'kw': ['the-kw-arg']}
When run via manage.py it also works as expected / per argparse:
$> ./manage.py commandbug "the-positional-arg" --kw "the-kw-arg" {'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'skip_checks': False, 'positional': ['the-positional-arg'], 'kw': ['the-kw-arg']}
Hopefully this makes sense, and is a useful observation.
On an unrelated note, thanks for all you do! Django has been a life changing framework for me.
Change History (3)
comment:1 by , 3 years ago
Component: | Uncategorized → Core (Management commands) |
---|
comment:2 by , 3 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:3 by , 3 years ago
Summary: | Call_command returns different values for options than manage.py (and itself) when nargs is specified → call_command() returns different values for options than manage.py when nargs is specified. |
---|
Thanks for the ticket, however it's documented that named options are passed without "triggering the argument parser, which means you’ll need to pass the correct type".
💗