#35926: Support capturing the remainder of a command-line arguments in
BaseCommand
-------------------------------------+-------------------------------------
Reporter: Daniel Quinn | Type: New
| feature
Status: new | Component: Core
| (Management commands)
Version: 5.1 | Severity: Normal
Keywords: management command, | Triage Stage:
remainder | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
I wanted to write a management command that would accept a few known
arguments and then capture the remaining arbitrary arguments passed as a
separate value. For example:
{{{
./manage.py mycommand --expected=argument --something-arbitrary -x -y -z
}}}
So `--expected-argument` would be defined in `.add_arguments()`, but the
other args would just be available as something like
`options["remainder"]` or whatever.
This is usually done by calling `parse_known_args()` rather than the more
common `.parse_args()`, but unfortunately there's currently no way to
cleanly indicate this with BaseCommand. The only way seems to be to
copy/paste the entirety of `BaseCommand.run_from_argv()` and then change
where`.parse_args()` is invoked:
{{{
def run_from_argv(self, argv):
"""
Copypasta from the parent class, so I can change `.parse_args()`
to
`.parse_known_args()`.
"""
self._called_from_command_line = True
parser = self.create_parser(argv[0], argv[1])
# Change
--------------------------------------------------------------
options, remainder = parser.parse_known_args(argv[2:])
cmd_options = vars(options)
cmd_options["remainder"] = remainder
# /Change
-------------------------------------------------------------
# Move positional args out of options to mimic legacy optparse
args = cmd_options.pop("args", ())
handle_default_options(options)
try:
self.execute(*args, **cmd_options)
except CommandError as e:
if options.traceback:
raise
# SystemCheckError takes care of its own formatting.
if isinstance(e, SystemCheckError):
self.stderr.write(str(e), lambda x: x)
else:
self.stderr.write("%s: %s" % (e.__class__.__name__, e))
sys.exit(e.returncode)
finally:
try:
connections.close_all()
except ImproperlyConfigured:
# Ignore if connections aren't setup at this point (e.g.
no
# configured settings).
pass
}}}
Obviously that's not ideal.
One option might be to just use `.parse_known_args()` and then allow the
user to indicate whether they want to capture the remainder or not, and if
so, as what attribute, but I have no strong feelings about implementation.
--
Ticket URL: <https://code.djangoproject.com/ticket/35926>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019349afe1a2-27c72894-23de-418f-8557-76cb920e13c2-000000%40eu-central-1.amazonses.com.