From b239bb7e87aa07e37d9166f1b21797f3f9a37983 Mon Sep 17 00:00:00 2001 From: joshuaswanson Date: Wed, 25 Mar 2026 20:59:58 +0100 Subject: [PATCH] gh-126676: Expand argparse docs for type=bool with warning and alternatives --- Doc/library/argparse.rst | 55 ++++++++++++++++++- ...-03-25-00-00-00.gh-issue-126676.052336.rst | 4 ++ 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 5a463ee9821d61..254d6b2ea794da 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1116,9 +1116,58 @@ User defined functions can be used as well: >>> parser.parse_args(['"The Tale of Two Cities"']) Namespace(short_title='"the-tale-of-two-citi') -The :func:`bool` function is not recommended as a type converter. All it does -is convert empty strings to ``False`` and non-empty strings to ``True``. -This is usually not what is desired. +.. warning:: + + The :func:`bool` function is not recommended as a type converter. All it + does is convert empty strings to ``False`` and non-empty strings to + ``True``. This is usually not what is desired:: + + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', type=bool) + >>> parser.parse_args(['--verbose', 'False']) + Namespace(verbose=True) + + ``'False'`` is a non-empty string, so :func:`bool` converts it to + ``True``. + + To handle boolean flags, use one of the following patterns instead: + + * For ``--flag``/``--no-flag`` style options, use + :class:`BooleanOptionalAction`:: + + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', action=argparse.BooleanOptionalAction) + >>> parser.parse_args(['--verbose']) + Namespace(verbose=True) + >>> parser.parse_args(['--no-verbose']) + Namespace(verbose=False) + + * For a flag that sets a ``True`` or ``False`` value, use + ``action='store_true'`` or ``action='store_false'``:: + + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', action='store_true') + >>> parser.parse_args(['--verbose']) + Namespace(verbose=True) + >>> parser.parse_args([]) + Namespace(verbose=False) + + * For a positional or option that accepts the strings ``'true'`` or + ``'false'``, define a converter function:: + + >>> def str_to_bool(value): + ... if value.casefold() in ('true', '1', 'yes'): + ... return True + ... elif value.casefold() in ('false', '0', 'no'): + ... return False + ... raise argparse.ArgumentTypeError(f'{value!r} is not a boolean value') + ... + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', type=str_to_bool) + >>> parser.parse_args(['--verbose', 'yes']) + Namespace(verbose=True) + >>> parser.parse_args(['--verbose', 'false']) + Namespace(verbose=False) In general, the ``type`` keyword is a convenience that should only be used for simple conversions that can only raise one of the three supported exceptions. diff --git a/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst b/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst new file mode 100644 index 00000000000000..f6c8b83d1c1582 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst @@ -0,0 +1,4 @@ +Expand :mod:`argparse` documentation for ``type=bool`` with a warning +admonition, a demonstration of the surprising behavior, and recommended +alternatives (``BooleanOptionalAction``, ``store_true``/``store_false``, +and a custom converter function).