summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHai Shi <shihai1992@gmail.com>2019-09-12 10:56:05 (GMT)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-09-12 10:56:05 (GMT)
commitf545638b5701652ffbe1774989533cdf5bc6631e (patch)
tree27c90f441b2aa84cf770ff3782550947b4ab36af
parent2d32bf1ef23c9e468b2e8afab3c24e7a2047ac36 (diff)
downloadcpython-f545638b5701652ffbe1774989533cdf5bc6631e.zip
cpython-f545638b5701652ffbe1774989533cdf5bc6631e.tar.gz
cpython-f545638b5701652ffbe1774989533cdf5bc6631e.tar.bz2
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
-rw-r--r--Doc/library/argparse.rst30
-rw-r--r--Lib/argparse.py26
-rw-r--r--Lib/test/test_argparse.py15
-rw-r--r--Misc/NEWS.d/next/Library/2019-08-21-16-38-56.bpo-9938.t3G7N9.rst1
4 files changed, 62 insertions, 10 deletions
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
index 368b1cf..c2cf7d3 100644
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -142,7 +142,7 @@ ArgumentParser objects
formatter_class=argparse.HelpFormatter, \
prefix_chars='-', fromfile_prefix_chars=None, \
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
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
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
*allow_abbrev* parameter was added.
@@ -186,6 +189,9 @@ ArgumentParser objects
In previous versions, *allow_abbrev* also disabled grouping of short
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.
@@ -647,6 +653,28 @@ the help options::
+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
-------------------------
diff --git a/Lib/argparse.py b/Lib/argparse.py
index ddfd772..2e46e76 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1630,6 +1630,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
- conflict_handler -- String indicating how to handle conflicts
- add_help -- Add a -h/-help option
- 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,
@@ -1644,7 +1646,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
argument_default=None,
conflict_handler='error',
add_help=True,
- allow_abbrev=True):
+ allow_abbrev=True,
+ exit_on_error=True):
superinit = super(ArgumentParser, self).__init__
superinit(description=description,
@@ -1663,6 +1666,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
self.fromfile_prefix_chars = fromfile_prefix_chars
self.add_help = add_help
self.allow_abbrev = allow_abbrev
+ self.exit_on_error = exit_on_error
add_group = self.add_argument_group
self._positionals = add_group(_('positional arguments'))
@@ -1793,15 +1797,19 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
setattr(namespace, dest, self._defaults[dest])
# parse the arguments and exit if there are any errors
- try:
+ if self.exit_on_error:
+ try:
+ 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):
- args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
- delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
- return namespace, args
- except ArgumentError:
- err = _sys.exc_info()[1]
- self.error(str(err))
+
+ if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
+ args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
+ delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
+ return namespace, args
def _parse_known_args(self, arg_strings, namespace):
# replace arg strings that are file references
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 86ec6cc..464db29 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -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():
support.run_unittest(__name__)
# Remove global references to avoid looking like we have refleaks.
diff --git a/Misc/NEWS.d/next/Library/2019-08-21-16-38-56.bpo-9938.t3G7N9.rst b/Misc/NEWS.d/next/Library/2019-08-21-16-38-56.bpo-9938.t3G7N9.rst
new file mode 100644
index 0000000..4cb8989
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-08-21-16-38-56.bpo-9938.t3G7N9.rst
@@ -0,0 +1 @@
+Add optional keyword argument ``exit_on_error`` for :class:`ArgumentParser`.