From 562039f287b7e9c3e35cb00ed8c27bc5883c761a Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sun, 27 Sep 2009 19:42:40 +0000 Subject: [PATCH] Add PEP 389: argparse - new command line parsing module. --- pep-0389.txt | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 pep-0389.txt diff --git a/pep-0389.txt b/pep-0389.txt new file mode 100644 index 000000000..5b2525070 --- /dev/null +++ b/pep-0389.txt @@ -0,0 +1,224 @@ +PEP: 389 +Title: argparse - new command line parsing module +Version: $Revision$ +Last-Modified: $Date$ +Author: Steven Bethard +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 25-Sep-2009 +Python-Version: 2.7 and 3.2 +Post-History: + + +Abstract +======== +This PEP proposes inclusion of the argparse [1]_ module in the Python +standard library in Python 2.7 and 3.2. + + +Motivation +========== +The argparse module is a command line parsing library which provides +more functionality than the existing command line parsing modules in +the standard library, getopt [2]_ and optparse [3]_. It includes +support for positional arguments (not just options), subcommands, +required options, options syntaxes like "/f" and "+rgb", zero-or-more +and one-or-more style arguments, and many other features the other +two lack. + +The argparse module is also already a popular third-party replacement +for these modules. It is used in projects like IPython (the Scipy +Python shell) [4]_, is included in Debian testing and unstable [5]_, +and since 2007 has had various requests for its inclusion in the +standard library [6]_ [7]_ [8]_. This popularity suggests it may be +a valuable addition to the Python libraries. + + +Why aren't getopt and optparse enough? +====================================== +One argument against adding argparse is that thare are "already two +different option parsing modules in the standard library" [9]_. The +following is a list of features provided by argparse but not present +in getopt or optparse: + +* While it is true there are two *option* parsing libraries, there + are no full command line parsing libraries -- both getopt and + optparse support only options and have no support for positional + arguments. The argparse module handles both, and as a result, is + able to generate better help messages, avoiding redundancies like + the ``usage=`` string usually required by optparse. + +* The argparse module values practicality over purity. Thus, argparse + allows required options and customization of which characters are + used to identify options, while optparse explicitly states "the + phrase 'required option' is self-contradictory" and that the option + syntaxes ``-pf``, ``-file``, ``+f``, ``+rgb``, ``/f`` and ``/file`` + "are not supported by optparse, and they never will be". + +* The argparse module allows options to accept a variable number of + arguments using ``nargs='?'``, ``nargs='*'`` or ``nargs='+'``. The + optparse module provides an untested recipe for some part of this + functionality [10]_ but admits that "things get hairy when you want + an option to take a variable number of arguments." + +* The argparse module supports subcommands, where a main command + line parser dispatches to other command line parsers depending on + the command line arguments. This is a common pattern in command + line interfaces, e.g. ``svn co`` and ``svn up``. + + +Why isn't the functionality just being added to optparse? +========================================================= +Clearly all the above features offer improvements over what is +available through optparse. A reasonable question then is why these +features are not simply provided as patches to optparse, instead of +introducing an entirely new module. In fact, the original development +of argparse intended to do just that, but because of various fairly +constraining design decisions of optparse, this wasn't really +possible. Some of the problems included: + +* The optparse module exposes the internals of its parsing algorithm. + In particular, ``parser.largs`` and ``parser.rargs`` are guaranteed + to be available to callbacks [11]_. This makes it extremely + difficult to improve the parsing algorithm as was necessary in + argparse for proper handling of positional arguments and variable + length arguments. For example, ``nargs='+'`` in argparse is matched + using regular expressions and thus has no notion of things like + ``parser.largs``. + +* The optparse extension APIs are extremely complex. For example, + just to use a simple custom string-to-object conversion function, + you have to subclass ``Option``, hack class attributes, and then + specify your custom option type to the parser, like this:: + + class MyOption(Option): + TYPES = Option.TYPES + ("mytype",) + TYPE_CHECKER = copy(Option.TYPE_CHECKER) + TYPE_CHECKER["mytype"] = check_mytype + parser = optparse.OptionParser(option_class=MyOption) + parser.add_option("-m", type="mytype") + + For comparison, argparse simply allows conversion functions to be + used as ``type=`` arguments directly, e.g.:: + + parser = argparse.ArgumentParser() + parser.add_option("-m", type=check_mytype) + + But given the baroque customization APIs of optparse, it is unclear + how such a feature should interact with those APIs, and it is + quite possible that introducing the simple argparse API would break + existing custom Option code. + +* Both optparse and argparse parse command line arguments and assign + them as attributes to an object returned by ``parse_args``. + However, the optparse module guarantees that the ``take_action`` + method of custom actions will always be passed a ``values`` object + which provides an ``ensure_value`` method [12]_, while the argparse + module allows attributes to be assigned to any object, e.g.:: + + foo_object = ... + parser.parse_args(namespace=foo_object) + foo_object.some_attribute_parsed_from_command_line + + Modifying optparse to allow any object to be passed in would be + difficult because simply passing the ``foo_object`` around instead + of a ``Values`` instance will break existing custom actions that + depend on the ``ensure_value`` method. + +Because of issues like these, which made it unreasonably difficult +for argparse to stay compatible with the optparse APIs, argparse was +developed as an independent module. Given these issues, merging all +the argparse features into optparse with no backwards +incompatibilities seems unlikely. + + +Deprecation of getopt and optparse +================================== +There is still some debate over the best way (if at all) to encourage +users to move from getopt and optparse to their replacement, +argparse. The current recommendation of this PEP is the following +conservative deprecation strategy: + +* Python 3.2, Python 2.7 and any later Python 2.X releases -- + PendingDeprecation warnings, which by default are not displayed, + and documentation notes directing users of getopt and optparse to + argparse. + +* Python 3.3 -- Same as above + +* Python 3.4 -- Deprecation warnings for getopt and optparse, which + by default *are* displayed. + +Though this is slower than the usual deprecation process, it seems +prudent to avoid producing any casually visible Deprecation warnings +until Python 3.X has had some additional time to attract developers. + + +Open Issues +=========== +The argparse module supports Python from 2.3 up through 3.2 and as a +result relies on traditional ``%(foo)s`` style string formatting. It +has been suggested that it might be better to use the new style +``{foo}`` string formatting [13]_. This seems like a good idea, but +would break backwards compatibility for existing argparse-based +scripts unless we can come up with a way to reasonably support both +syntaxes. + + +References +========== +.. [1] argparse + (http://code.google.com/p/argparse/) + +.. [2] getopt + (http://docs.python.org/library/getopt.html) + +.. [3] optparse + (http://docs.python.org/library/optparse.html) + +.. [4] argparse in IPython + (http://mail.scipy.org/pipermail/ipython-dev/2009-April/005102.html) + +.. [5] argparse in Debian + (http://packages.debian.org/search?keywords=python-argparse) + +.. [6] 2007-01-03 request for argparse in the standard library + (http://mail.python.org/pipermail/python-list/2007-January/592646.html) + +.. [7] 2009-06-09 request for argparse in the standard library + (http://bugs.python.org/issue6247) + +.. [8] 2009-09-10 request for argparse in the standard library + (http://mail.python.org/pipermail/stdlib-sig/2009-September/000342.html) + +.. [9] Fredrik Lundh response to [6]_ + (http://mail.python.org/pipermail/python-list/2007-January/592675.html) + +.. [10] optparse variable args + (http://docs.python.org/library/optparse.html#callback-example-6-variable-arguments) + +.. [11] parser.largs and parser.rargs + (http://docs.python.org/library/optparse.html#how-callbacks-are-called) + +.. [12] take_action values argument + (http://docs.python.org/library/optparse.html#adding-new-actions) + +.. [13] use {}-formatting instead of %-formatting + (http://bugs.python.org/msg89279) + + +Copyright +========= +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: