[Django] #29295: BaseCommand.add_arguments does not allow parser.add_subparsers().add_parser("subcommand")

11 views
Skip to first unread message

Django

unread,
Apr 6, 2018, 8:32:43 AM4/6/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments does not allow
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------
Reporter: Lutz | Owner: nobody
Prechelt |
Type: Bug | Status: new
Component: Core | Version: 1.11
(Management commands) | Keywords: BaseCommand
Severity: Normal | argparse subparser add_subparsers
Triage Stage: | add_parser
Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
== 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.)

--
Ticket URL: <https://code.djangoproject.com/ticket/29295>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 6, 2018, 10:52:23 AM4/6/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------
Reporter: Lutz Prechelt | Owner: nobody
Type: Bug | Status: new
Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution:
Keywords: BaseCommand | Triage Stage: Accepted
argparse subparser add_subparsers |
add_parser |

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted


Comment:

While investigating the issue, I wrote a patch that I think should solve
the issue. What remains is to add a test, probably in
`tests/user_commands`. What you like to try that?

--
Ticket URL: <https://code.djangoproject.com/ticket/29295#comment:1>

Django

unread,
Apr 6, 2018, 10:52:36 AM4/6/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------
Reporter: Lutz Prechelt | Owner: nobody
Type: Bug | Status: new

Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution:
Keywords: BaseCommand | Triage Stage: Accepted
argparse subparser add_subparsers |
add_parser |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* Attachment "29295.diff" added.

Django

unread,
Apr 13, 2018, 6:53:51 AM4/13/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------
Reporter: Lutz Prechelt | Owner: nobody
Type: Bug | Status: new

Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution:
Keywords: BaseCommand | Triage Stage: Accepted
argparse subparser add_subparsers |
add_parser |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Lutz Prechelt):

Yes, will try.
I have started to work my way into Django development (the new-developer
docs appear to be very good), but have a lot of the way left to go. Will
take a while, but I'll get to it eventually.

--
Ticket URL: <https://code.djangoproject.com/ticket/29295#comment:2>

Django

unread,
Apr 13, 2018, 6:54:11 AM4/13/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------
Reporter: Lutz Prechelt | Owner: Lutz
| Prechelt
Type: Bug | Status: assigned

Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution:
Keywords: BaseCommand | Triage Stage: Accepted
argparse subparser add_subparsers |
add_parser |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Lutz Prechelt):

* status: new => assigned
* owner: nobody => Lutz Prechelt


--
Ticket URL: <https://code.djangoproject.com/ticket/29295#comment:3>

Django

unread,
Apr 21, 2018, 5:35:15 PM4/21/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------

Reporter: Lutz Prechelt | Owner: Lutz
| Prechelt
Type: Bug | Status: assigned
Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution:
Keywords: BaseCommand | Triage Stage: Ready for
argparse subparser add_subparsers | checkin
add_parser |
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* has_patch: 0 => 1
* stage: Accepted => Ready for checkin


Comment:

[https://github.com/django/django/pull/9894 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/29295#comment:4>

Django

unread,
Apr 21, 2018, 5:59:32 PM4/21/18
to django-...@googlegroups.com
#29295: BaseCommand.add_arguments crashes when using
parser.add_subparsers().add_parser("subcommand")
-------------------------------------+-------------------------------------

Reporter: Lutz Prechelt | Owner: Lutz
| Prechelt
Type: Bug | Status: closed

Component: Core (Management | Version: 1.11
commands) |
Severity: Normal | Resolution: fixed

Keywords: BaseCommand | Triage Stage: Ready for
argparse subparser add_subparsers | checkin
add_parser |
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"dd68b51e1da54267bde4799fa0d9fbd4290eb8b5" dd68b51e]:
{{{
#!CommitTicketReference repository=""
revision="dd68b51e1da54267bde4799fa0d9fbd4290eb8b5"
Fixed #29295 -- Fixed management command crash when using subparsers.

Thanks Tim Graham for the fix.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/29295#comment:5>

Reply all
Reply to author
Forward
0 new messages