Issue #14910: Add allow_abbrev parameter to argparse.ArgumentParser.

Patch by Jonathan Paugh, Steven Bethard, paul j3 and Daniel Eriksson.
This commit is contained in:
Berker Peksag 2015-02-14 01:39:17 +02:00
parent 0fe6325acf
commit 8089cd642f
5 changed files with 95 additions and 20 deletions

View File

@ -135,7 +135,7 @@ ArgumentParser objects
formatter_class=argparse.HelpFormatter, \ formatter_class=argparse.HelpFormatter, \
prefix_chars='-', fromfile_prefix_chars=None, \ prefix_chars='-', fromfile_prefix_chars=None, \
argument_default=None, conflict_handler='error', \ argument_default=None, conflict_handler='error', \
add_help=True) add_help=True, allow_abbrev=True)
Create a new :class:`ArgumentParser` object. All parameters should be passed Create a new :class:`ArgumentParser` object. All parameters should be passed
as keyword arguments. Each parameter has its own more detailed description as keyword arguments. Each parameter has its own more detailed description
@ -169,6 +169,12 @@ ArgumentParser objects
* add_help_ - Add a -h/--help option to the parser (default: ``True``) * add_help_ - Add a -h/--help option to the parser (default: ``True``)
* allow_abbrev_ - Allows long options to be abbreviated if the
abbreviation is unambiguous. (default: ``True``)
.. versionchanged:: 3.5
*allow_abbrev* parameter was added.
The following sections describe how each of these are used. The following sections describe how each of these are used.
@ -518,6 +524,26 @@ calls, we supply ``argument_default=SUPPRESS``::
>>> parser.parse_args([]) >>> parser.parse_args([])
Namespace() Namespace()
.. _allow_abbrev:
allow_abbrev
^^^^^^^^^^^^
Normally, when you pass an argument list to the
:meth:`~ArgumentParser.parse_args` method of a :class:`ArgumentParser`,
it :ref:`recognizes abbreviations <prefix-matching>` of long options.
This feature can be disabled by setting ``allow_abbrev`` to ``False``::
>>> parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False)
>>> parser.add_argument('--foobar', action='store_true')
>>> parser.add_argument('--foonley', action='store_false')
>>> parser.parse_args([--foon])
usage: PROG [-h] [--foobar] [--foonley]
PROG: error: unrecognized arguments: --foon
.. versionadded:: 3.5
conflict_handler conflict_handler
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -1410,9 +1436,9 @@ argument::
Argument abbreviations (prefix matching) Argument abbreviations (prefix matching)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :meth:`~ArgumentParser.parse_args` method allows long options to be The :meth:`~ArgumentParser.parse_args` method :ref:`by default <allow_abbrev>`
abbreviated to a prefix, if the abbreviation is unambiguous (the prefix matches allows long options to be abbreviated to a prefix, if the abbreviation is
a unique option):: unambiguous (the prefix matches a unique option)::
>>> parser = argparse.ArgumentParser(prog='PROG') >>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-bacon') >>> parser.add_argument('-bacon')
@ -1426,6 +1452,7 @@ a unique option)::
PROG: error: ambiguous option: -ba could match -badger, -bacon PROG: error: ambiguous option: -ba could match -badger, -bacon
An error is produced for arguments that could produce more than one options. An error is produced for arguments that could produce more than one options.
This feature can be disabled by setting :ref:`allow_abbrev` to ``False``.
Beyond ``sys.argv`` Beyond ``sys.argv``

View File

@ -146,6 +146,14 @@ New Modules
Improved Modules Improved Modules
================ ================
argparse
--------
* :class:`~argparse.ArgumentParser` now allows to disable
:ref:`abbreviated usage <prefix-matching>` of long options by setting
:ref:`allow_abbrev` to ``False``.
(Contributed by Jonathan Paugh, Steven Bethard, paul j3 and Daniel Eriksson.)
cgi cgi
--- ---

View File

@ -1590,6 +1590,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
- argument_default -- The default value for all arguments - argument_default -- The default value for all arguments
- conflict_handler -- String indicating how to handle conflicts - conflict_handler -- String indicating how to handle conflicts
- add_help -- Add a -h/-help option - add_help -- Add a -h/-help option
- allow_abbrev -- Allow long options to be abbreviated unambiguously
""" """
def __init__(self, def __init__(self,
@ -1603,7 +1604,8 @@ def __init__(self,
fromfile_prefix_chars=None, fromfile_prefix_chars=None,
argument_default=None, argument_default=None,
conflict_handler='error', conflict_handler='error',
add_help=True): add_help=True,
allow_abbrev=True):
superinit = super(ArgumentParser, self).__init__ superinit = super(ArgumentParser, self).__init__
superinit(description=description, superinit(description=description,
@ -1621,6 +1623,7 @@ def __init__(self,
self.formatter_class = formatter_class self.formatter_class = formatter_class
self.fromfile_prefix_chars = fromfile_prefix_chars self.fromfile_prefix_chars = fromfile_prefix_chars
self.add_help = add_help self.add_help = add_help
self.allow_abbrev = allow_abbrev
add_group = self.add_argument_group add_group = self.add_argument_group
self._positionals = add_group(_('positional arguments')) self._positionals = add_group(_('positional arguments'))
@ -2098,6 +2101,7 @@ def _parse_optional(self, arg_string):
action = self._option_string_actions[option_string] action = self._option_string_actions[option_string]
return action, option_string, explicit_arg return action, option_string, explicit_arg
if self.allow_abbrev:
# search through all possible prefixes of the option string # search through all possible prefixes of the option string
# and all actions in the parser for possible interpretations # and all actions in the parser for possible interpretations
option_tuples = self._get_option_tuples(arg_string) option_tuples = self._get_option_tuples(arg_string)

View File

@ -753,6 +753,39 @@ class TestOptionalsActionCount(ParserTestCase):
] ]
class TestOptionalsAllowLongAbbreviation(ParserTestCase):
"""Allow long options to be abbreviated unambiguously"""
argument_signatures = [
Sig('--foo'),
Sig('--foobaz'),
Sig('--fooble', action='store_true'),
]
failures = ['--foob 5', '--foob']
successes = [
('', NS(foo=None, foobaz=None, fooble=False)),
('--foo 7', NS(foo='7', foobaz=None, fooble=False)),
('--fooba a', NS(foo=None, foobaz='a', fooble=False)),
('--foobl --foo g', NS(foo='g', foobaz=None, fooble=True)),
]
class TestOptionalsDisallowLongAbbreviation(ParserTestCase):
"""Do not allow abbreviations of long options at all"""
parser_signature = Sig(allow_abbrev=False)
argument_signatures = [
Sig('--foo'),
Sig('--foodle', action='store_true'),
Sig('--foonly'),
]
failures = ['-foon 3', '--foon 3', '--food', '--food --foo 2']
successes = [
('', NS(foo=None, foodle=False, foonly=None)),
('--foo 3', NS(foo='3', foodle=False, foonly=None)),
('--foonly 7 --foodle --foo 2', NS(foo='2', foodle=True, foonly='7')),
]
# ================ # ================
# Positional tests # Positional tests
# ================ # ================

View File

@ -13,6 +13,9 @@ Core and Builtins
Library Library
------- -------
- Issue #14910: Add allow_abbrev parameter to argparse.ArgumentParser. Patch by
Jonathan Paugh, Steven Bethard, paul j3 and Daniel Eriksson.
- Issue #21717: tarfile.open() now supports 'x' (exclusive creation) mode. - Issue #21717: tarfile.open() now supports 'x' (exclusive creation) mode.
- Issue #23344: marshal.dumps() is now 20-25% faster on average. - Issue #23344: marshal.dumps() is now 20-25% faster on average.