From 0ad173249d287794d53e6a1fe2d58bb2adee2276 Mon Sep 17 00:00:00 2001 From: Jack DeVries <58614260+jdevries3133@users.noreply.github.com> Date: Sat, 31 Jul 2021 12:27:55 -0400 Subject: bpo-37880: for argparse add_argument with action='store_const', const now defaults to None. (GH-26707) --- Doc/library/argparse.rst | 27 +++++++++++++--------- Lib/argparse.py | 5 ++-- Lib/test/test_argparse.py | 19 +++++++++++++++ .../2021-06-13-00-16-56.bpo-37880.5bTrkw.rst | 3 +++ 4 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-06-13-00-16-56.bpo-37880.5bTrkw.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index a1b4bd0..ac8a2fd 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -722,8 +722,9 @@ The :meth:`~ArgumentParser.add_argument` method must know whether an optional argument, like ``-f`` or ``--foo``, or a positional argument, like a list of filenames, is expected. The first arguments passed to :meth:`~ArgumentParser.add_argument` must therefore be either a series of -flags, or a simple argument name. For example, an optional argument could -be created like:: +flags, or a simple argument name. + +For example, an optional argument could be created like:: >>> parser.add_argument('-f', '--foo') @@ -765,8 +766,9 @@ how the command-line arguments should be handled. The supplied actions are: Namespace(foo='1') * ``'store_const'`` - This stores the value specified by the const_ keyword - argument. The ``'store_const'`` action is most commonly used with - optional arguments that specify some sort of flag. For example:: + argument; note that the const_ keyword argument defaults to ``None``. The + ``'store_const'`` action is most commonly used with optional arguments that + specify some sort of flag. For example:: >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_const', const=42) @@ -795,8 +797,8 @@ how the command-line arguments should be handled. The supplied actions are: Namespace(foo=['1', '2']) * ``'append_const'`` - This stores a list, and appends the value specified by - the const_ keyword argument to the list. (Note that the const_ keyword - argument defaults to ``None``.) The ``'append_const'`` action is typically + the const_ keyword argument to the list; note that the const_ keyword + argument defaults to ``None``. The ``'append_const'`` action is typically useful when multiple arguments need to store constants to the same list. For example:: @@ -979,17 +981,20 @@ the various :class:`ArgumentParser` actions. The two most common uses of it are ``action='store_const'`` or ``action='append_const'``. These actions add the ``const`` value to one of the attributes of the object returned by :meth:`~ArgumentParser.parse_args`. See the action_ description for examples. + If ``const`` is not provided to :meth:`~ArgumentParser.add_argument`, it will + receive a default value of ``None``. + * When :meth:`~ArgumentParser.add_argument` is called with option strings (like ``-f`` or ``--foo``) and ``nargs='?'``. This creates an optional argument that can be followed by zero or one command-line arguments. When parsing the command line, if the option string is encountered with no - command-line argument following it, the value of ``const`` will be assumed instead. - See the nargs_ description for examples. - -With the ``'store_const'`` and ``'append_const'`` actions, the ``const`` -keyword argument must be given. For other actions, it defaults to ``None``. + command-line argument following it, the value of ``const`` will be assumed to + be ``None`` instead. See the nargs_ description for examples. +.. versionchanged:: 3.11 + ``const=None`` by default, including when ``action='append_const'`` or + ``action='store_const'``. default ^^^^^^^ diff --git a/Lib/argparse.py b/Lib/argparse.py index e3a49e7..33c5d70 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -855,6 +855,7 @@ class Action(_AttributeHolder): def __call__(self, parser, namespace, values, option_string=None): raise NotImplementedError(_('.__call__() not defined')) + class BooleanOptionalAction(Action): def __init__(self, option_strings, @@ -936,7 +937,7 @@ class _StoreConstAction(Action): def __init__(self, option_strings, dest, - const, + const=None, default=None, required=False, help=None, @@ -1031,7 +1032,7 @@ class _AppendConstAction(Action): def __init__(self, option_strings, dest, - const, + const=None, default=None, required=False, help=None, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 0994e70..93ac0c3 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -745,6 +745,25 @@ class TestOptionalsActionAppendWithDefault(ParserTestCase): ] +class TestConstActionsMissingConstKwarg(ParserTestCase): + """Tests that const gets default value of None when not provided""" + + argument_signatures = [ + Sig('-f', action='append_const'), + Sig('--foo', action='append_const'), + Sig('-b', action='store_const'), + Sig('--bar', action='store_const') + ] + failures = ['-f v', '--foo=bar', '--foo bar'] + successes = [ + ('', NS(f=None, foo=None, b=None, bar=None)), + ('-f', NS(f=[None], foo=None, b=None, bar=None)), + ('--foo', NS(f=None, foo=[None], b=None, bar=None)), + ('-b', NS(f=None, foo=None, b=None, bar=None)), + ('--bar', NS(f=None, foo=None, b=None, bar=None)), + ] + + class TestOptionalsActionAppendConst(ParserTestCase): """Tests the append_const action for an Optional""" diff --git a/Misc/NEWS.d/next/Library/2021-06-13-00-16-56.bpo-37880.5bTrkw.rst b/Misc/NEWS.d/next/Library/2021-06-13-00-16-56.bpo-37880.5bTrkw.rst new file mode 100644 index 0000000..4282157 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-06-13-00-16-56.bpo-37880.5bTrkw.rst @@ -0,0 +1,3 @@ +argparse actions store_const and append_const each receive a default value +of None when the ``const`` kwarg is not provided. Previously, this raised a +:exc:`TypeError`. -- cgit v0.12