﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
29295	"BaseCommand.add_arguments crashes when using parser.add_subparsers().add_parser(""subcommand"")"	Lutz Prechelt	Lutz Prechelt	"== Background

Python's [https://docs.python.org/3/library/argparse.html argparse] allows to [https://docs.python.org/3/library/argparse.html?highlight=argparse#sub-commands define subparsers].
The following works (but does nothing observable) in plain Python:

{{{
import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
a_parser = subparsers.add_parser(""A"")
}}}

== Setup

The equivalent does ''not'' work in a `manage.py` custom command.
When I put this in file **`mycommand.py`**:
{{{
import django.core.management.base as djcmb

class Command(djcmb.BaseCommand):
    def add_arguments(self, parser):
        subparsers = parser.add_subparsers()
        a_parser = subparsers.add_parser(""A"")
}}}

== Symptom

...and then run **`python manage.py mycommand A`**,
what I get is `TypeError: __init__() missing 1 required positional argument: 'cmd'` with the following stacktrace:
{{{
  File ""manage.py"", line 8, in <module>
    execute_from_command_line(sys.argv)
  File ""C:\venv\rqc36\lib\site-packages\django\core\management\__init__.py"", line 364, in execute_from_command_line
    utility.execute()
  File ""C:\venv\rqc36\lib\site-packages\django\core\management\__init__.py"", line 356, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ""C:\venv\rqc36\lib\site-packages\django\core\management\base.py"", line 275, in run_from_argv
    parser = self.create_parser(argv[0], argv[1])
  File ""C:\venv\rqc36\lib\site-packages\django\core\management\base.py"", line 249, in create_parser
    self.add_arguments(parser)
  File ""C:\ws\bb\rqc\rqc\management\commands\mycommand.py"", line 7, in add_arguments
    a_parser = subparsers.add_parser(""A"")
  File ""C:\sw\Python36-32\lib\argparse.py"", line 1097, in add_parser
    parser = self._parser_class(**kwargs)
}}}

== Diagnosis

The reason is that Django does not use a plain `ArgumentParser` but rather its own `django.core.management.base.CommandParser`, the constructor of which requires a positional argument:
{{{
    def __init__(self, cmd, **kwargs):  # ...
}}}
where `cmd` is supposed to contain the `mycommand.Command` object which is then stored as `self.cmd` in the parser.

The following **kludge** helps the poor user trying to get subparsers to work:
{{{
import argparse
import django.core.management.base as djcmb

class Command(djcmb.BaseCommand):
    def add_arguments(self, parser):
        subparsers = parser.add_subparsers()
        subparsers._parser_class = argparse.ArgumentParser  # circumvent Django 1.11 bug
        a_parser = subparsers.add_parser(""A"")

}}}

== Repair suggestions

**S1**: The most straightforward repair I see would be to make the argument optional (`*argv`) and use a dummy object for `self.cmd` in case of subparsers. `self.cmd` is used only three times. Is this good enough?

**S2**: Alternatively, one could simply document the problem and the kludge. (BTW: The custom commands how-to should become more explicit regarding the use of `argparse`; it is currently only hinted at, never mentioned.)"	Bug	closed	Core (Management commands)	1.11	Normal	fixed	BaseCommand argparse subparser add_subparsers add_parser		Ready for checkin	1	0	0	0	0	0
