mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-9938: Add optional keyword argument exit_on_error to argparse.ArgumentParser (GH-15362)
Co-Authored-by: Xuanji Li <xuanji@gmail.com> https://bugs.python.org/issue9938 Automerge-Triggered-By: @matrixise
This commit is contained in:
parent
2d32bf1ef2
commit
f545638b57
4 changed files with 62 additions and 10 deletions
|
@ -142,7 +142,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, allow_abbrev=True)
|
add_help=True, allow_abbrev=True, exit_on_error=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
|
||||||
|
@ -179,6 +179,9 @@ ArgumentParser objects
|
||||||
* allow_abbrev_ - Allows long options to be abbreviated if the
|
* allow_abbrev_ - Allows long options to be abbreviated if the
|
||||||
abbreviation is unambiguous. (default: ``True``)
|
abbreviation is unambiguous. (default: ``True``)
|
||||||
|
|
||||||
|
* exit_on_error_ - Determines whether or not ArgumentParser exits with
|
||||||
|
error info when an error occurs. (default: ``True``)
|
||||||
|
|
||||||
.. versionchanged:: 3.5
|
.. versionchanged:: 3.5
|
||||||
*allow_abbrev* parameter was added.
|
*allow_abbrev* parameter was added.
|
||||||
|
|
||||||
|
@ -186,6 +189,9 @@ ArgumentParser objects
|
||||||
In previous versions, *allow_abbrev* also disabled grouping of short
|
In previous versions, *allow_abbrev* also disabled grouping of short
|
||||||
flags such as ``-vv`` to mean ``-v -v``.
|
flags such as ``-vv`` to mean ``-v -v``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
*exit_on_error* parameter was added.
|
||||||
|
|
||||||
The following sections describe how each of these are used.
|
The following sections describe how each of these are used.
|
||||||
|
|
||||||
|
|
||||||
|
@ -647,6 +653,28 @@ the help options::
|
||||||
+h, ++help show this help message and exit
|
+h, ++help show this help message and exit
|
||||||
|
|
||||||
|
|
||||||
|
exit_on_error
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Normally, when you pass an invalid argument list to the :meth:`~ArgumentParser.parse_args`
|
||||||
|
method of an :class:`ArgumentParser`, it will exit with error info.
|
||||||
|
|
||||||
|
If the user would like catch errors manually, the feature can be enable by setting
|
||||||
|
``exit_on_error`` to ``False``::
|
||||||
|
|
||||||
|
>>> parser = argparse.ArgumentParser(exit_on_error=False)
|
||||||
|
>>> parser.add_argument('--integers', type=int)
|
||||||
|
_StoreAction(option_strings=['--integers'], dest='integers', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
|
||||||
|
>>> try:
|
||||||
|
... parser.parse_args('--integers a'.split())
|
||||||
|
... except argparse.ArgumentError:
|
||||||
|
... print('Catching an argumentError')
|
||||||
|
...
|
||||||
|
Catching an argumentError
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
The add_argument() method
|
The add_argument() method
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
|
@ -1630,6 +1630,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
- 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
|
- allow_abbrev -- Allow long options to be abbreviated unambiguously
|
||||||
|
- exit_on_error -- Determines whether or not ArgumentParser exits with
|
||||||
|
error info when an error occurs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
@ -1644,7 +1646,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
argument_default=None,
|
argument_default=None,
|
||||||
conflict_handler='error',
|
conflict_handler='error',
|
||||||
add_help=True,
|
add_help=True,
|
||||||
allow_abbrev=True):
|
allow_abbrev=True,
|
||||||
|
exit_on_error=True):
|
||||||
|
|
||||||
superinit = super(ArgumentParser, self).__init__
|
superinit = super(ArgumentParser, self).__init__
|
||||||
superinit(description=description,
|
superinit(description=description,
|
||||||
|
@ -1663,6 +1666,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
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
|
self.allow_abbrev = allow_abbrev
|
||||||
|
self.exit_on_error = exit_on_error
|
||||||
|
|
||||||
add_group = self.add_argument_group
|
add_group = self.add_argument_group
|
||||||
self._positionals = add_group(_('positional arguments'))
|
self._positionals = add_group(_('positional arguments'))
|
||||||
|
@ -1793,15 +1797,19 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
setattr(namespace, dest, self._defaults[dest])
|
setattr(namespace, dest, self._defaults[dest])
|
||||||
|
|
||||||
# parse the arguments and exit if there are any errors
|
# parse the arguments and exit if there are any errors
|
||||||
|
if self.exit_on_error:
|
||||||
try:
|
try:
|
||||||
namespace, args = self._parse_known_args(args, namespace)
|
namespace, args = self._parse_known_args(args, namespace)
|
||||||
|
except ArgumentError:
|
||||||
|
err = _sys.exc_info()[1]
|
||||||
|
self.error(str(err))
|
||||||
|
else:
|
||||||
|
namespace, args = self._parse_known_args(args, namespace)
|
||||||
|
|
||||||
if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
|
if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
|
||||||
args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
|
args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
|
||||||
delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
|
delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
|
||||||
return namespace, args
|
return namespace, args
|
||||||
except ArgumentError:
|
|
||||||
err = _sys.exc_info()[1]
|
|
||||||
self.error(str(err))
|
|
||||||
|
|
||||||
def _parse_known_args(self, arg_strings, namespace):
|
def _parse_known_args(self, arg_strings, namespace):
|
||||||
# replace arg strings that are file references
|
# replace arg strings that are file references
|
||||||
|
|
|
@ -5262,6 +5262,21 @@ class TestWrappingMetavar(TestCase):
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
|
||||||
|
class TestExitOnError(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.parser = argparse.ArgumentParser(exit_on_error=False)
|
||||||
|
self.parser.add_argument('--integers', metavar='N', type=int)
|
||||||
|
|
||||||
|
def test_exit_on_error_with_good_args(self):
|
||||||
|
ns = self.parser.parse_args('--integers 4'.split())
|
||||||
|
self.assertEqual(ns, argparse.Namespace(integers=4))
|
||||||
|
|
||||||
|
def test_exit_on_error_with_bad_args(self):
|
||||||
|
with self.assertRaises(argparse.ArgumentError):
|
||||||
|
self.parser.parse_args('--integers a'.split())
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(__name__)
|
support.run_unittest(__name__)
|
||||||
# Remove global references to avoid looking like we have refleaks.
|
# Remove global references to avoid looking like we have refleaks.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add optional keyword argument ``exit_on_error`` for :class:`ArgumentParser`.
|
Loading…
Add table
Add a link
Reference in a new issue