[Python-checkins] cpython: Issue #14910: Add allow_abbrev parameter to argparse.ArgumentParser.
berker.peksag
python-checkins at python.org
Sat Feb 14 00:40:15 CET 2015
https://hg.python.org/cpython/rev/99302634d756
changeset: 94605:99302634d756
user: Berker Peksag <berker.peksag at gmail.com>
date: Sat Feb 14 01:39:17 2015 +0200
summary:
Issue #14910: Add allow_abbrev parameter to argparse.ArgumentParser.
Patch by Jonathan Paugh, Steven Bethard, paul j3 and Daniel Eriksson.
files:
Doc/library/argparse.rst | 35 ++++++++++++++++++++--
Doc/whatsnew/3.5.rst | 8 +++++
Lib/argparse.py | 40 ++++++++++++++------------
Lib/test/test_argparse.py | 33 ++++++++++++++++++++++
Misc/NEWS | 3 ++
5 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -135,7 +135,7 @@
formatter_class=argparse.HelpFormatter, \
prefix_chars='-', fromfile_prefix_chars=None, \
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
as keyword arguments. Each parameter has its own more detailed description
@@ -169,6 +169,12 @@
* 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.
@@ -518,6 +524,26 @@
>>> parser.parse_args([])
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
^^^^^^^^^^^^^^^^
@@ -1410,9 +1436,9 @@
Argument abbreviations (prefix matching)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The :meth:`~ArgumentParser.parse_args` method allows long options to be
-abbreviated to a prefix, if the abbreviation is unambiguous (the prefix matches
-a unique option)::
+The :meth:`~ArgumentParser.parse_args` method :ref:`by default <allow_abbrev>`
+allows long options to be abbreviated to a prefix, if the abbreviation is
+unambiguous (the prefix matches a unique option)::
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-bacon')
@@ -1426,6 +1452,7 @@
PROG: error: ambiguous option: -ba could match -badger, -bacon
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``
diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -146,6 +146,14 @@
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
---
diff --git a/Lib/argparse.py b/Lib/argparse.py
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1590,6 +1590,7 @@
- argument_default -- The default value for all arguments
- conflict_handler -- String indicating how to handle conflicts
- add_help -- Add a -h/-help option
+ - allow_abbrev -- Allow long options to be abbreviated unambiguously
"""
def __init__(self,
@@ -1603,7 +1604,8 @@
fromfile_prefix_chars=None,
argument_default=None,
conflict_handler='error',
- add_help=True):
+ add_help=True,
+ allow_abbrev=True):
superinit = super(ArgumentParser, self).__init__
superinit(description=description,
@@ -1621,6 +1623,7 @@
self.formatter_class = formatter_class
self.fromfile_prefix_chars = fromfile_prefix_chars
self.add_help = add_help
+ self.allow_abbrev = allow_abbrev
add_group = self.add_argument_group
self._positionals = add_group(_('positional arguments'))
@@ -2098,23 +2101,24 @@
action = self._option_string_actions[option_string]
return action, option_string, explicit_arg
- # search through all possible prefixes of the option string
- # and all actions in the parser for possible interpretations
- option_tuples = self._get_option_tuples(arg_string)
-
- # if multiple actions match, the option string was ambiguous
- if len(option_tuples) > 1:
- options = ', '.join([option_string
- for action, option_string, explicit_arg in option_tuples])
- args = {'option': arg_string, 'matches': options}
- msg = _('ambiguous option: %(option)s could match %(matches)s')
- self.error(msg % args)
-
- # if exactly one action matched, this segmentation is good,
- # so return the parsed action
- elif len(option_tuples) == 1:
- option_tuple, = option_tuples
- return option_tuple
+ if self.allow_abbrev:
+ # search through all possible prefixes of the option string
+ # and all actions in the parser for possible interpretations
+ option_tuples = self._get_option_tuples(arg_string)
+
+ # if multiple actions match, the option string was ambiguous
+ if len(option_tuples) > 1:
+ options = ', '.join([option_string
+ for action, option_string, explicit_arg in option_tuples])
+ args = {'option': arg_string, 'matches': options}
+ msg = _('ambiguous option: %(option)s could match %(matches)s')
+ self.error(msg % args)
+
+ # if exactly one action matched, this segmentation is good,
+ # so return the parsed action
+ elif len(option_tuples) == 1:
+ option_tuple, = option_tuples
+ return option_tuple
# if it was not found as an option, but it looks like a negative
# number, it was meant to be positional
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -753,6 +753,39 @@
]
+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
# ================
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,9 @@
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 #23344: marshal.dumps() is now 20-25% faster on average.
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list