diff --git a/Lib/argparse.py b/Lib/argparse.py index 4f3aea928bf6f4..1b192badc024d3 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1602,6 +1602,22 @@ def _remove_action(self, action): self._container._remove_action(action) self._group_actions.remove(action) +def _strtobool (val): + """Convert a string representation of truth to true or false. + + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values + are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if + 'val' is anything else. + + + """ + val = val.lower() + if val in ('y', 'yes', 't', 'true', 'on', '1'): + return True + elif val in ('n', 'no', 'f', 'false', 'off', '0'): + return False + else: + raise ValueError("invalid truth value %r" % (val,)) class ArgumentParser(_AttributeHolder, _ActionsContainer): """Object for parsing command line strings into Python objects. @@ -1664,6 +1680,9 @@ def identity(string): return string self.register('type', None, identity) + # register bool with a type_func that translates string into bool instance logically and gracefully + self.register('type', bool, _strtobool) + # add help argument if necessary # (using explicit default to override global argument_default) default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 9079d4bc7aa7fd..5aec281081a1a9 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1650,6 +1650,29 @@ class TestTypeCallable(ParserTestCase): ('1024.675', NS(eggs=None, spam=1024.675)), ] +class TestTypeBool(ParserTestCase): + """Test some args with bool type:""" + + argument_signatures = [ + Sig('mybool', type=bool), + ] + failures = ['wrong','123','-1','abc','!@#'] + successes = [ + ('True', NS(mybool=True)), + ('False', NS(mybool=False)), + ('tRuE', NS(mybool=True)), + ('fAlSe', NS(mybool=False)), + ('yes', NS(mybool=True)), + ('no', NS(mybool=False)), + ('y', NS(mybool=True)), + ('n', NS(mybool=False)), + ('t', NS(mybool=True)), + ('f', NS(mybool=False)), + ('on', NS(mybool=True)), + ('off', NS(mybool=False)), + ('1', NS(mybool=True)), + ('0', NS(mybool=False)), + ] class TestTypeUserDefined(ParserTestCase): """Test a user-defined option/argument type""" diff --git a/Misc/NEWS.d/next/Library/2019-07-15-22-00-00.bpo-37564.L4ftF7.rst b/Misc/NEWS.d/next/Library/2019-07-15-22-00-00.bpo-37564.L4ftF7.rst new file mode 100644 index 00000000000000..33002a63dd48c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-15-22-00-00.bpo-37564.L4ftF7.rst @@ -0,0 +1,3 @@ +Fix ArgumentParser to treat ``type=bool`` according to common truth values. +Values 'y', 'yes', 't', 'true', 'on', and '1' will be evaluated as True value, +while 'n', 'no', 'f', 'false', 'off', and '0 will be evaluated as False value. \ No newline at end of file