#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.

Reply via email to