diff --git a/Lib/argparse.py b/Lib/argparse.py index 7988c447d03584..da3fbeee8f22d9 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -2009,11 +2009,9 @@ def consume_optional(start_index): explicit_arg = explicit_arg[1:] if not explicit_arg: sep = explicit_arg = None - elif explicit_arg[0] == '=': - sep = '=' - explicit_arg = explicit_arg[1:] else: sep = '' + continue else: extras.append(char + explicit_arg) stop = start_index + 1 @@ -2261,7 +2259,11 @@ def _parse_optional(self, arg_string): option_string, sep, explicit_arg = arg_string.partition('=') if sep and option_string in self._option_string_actions: action = self._option_string_actions[option_string] - return action, option_string, sep, explicit_arg + if arg_string[1] not in self.prefix_chars and len(option_string) == 2: + # Short option with an argument starting with "=". + return action, option_string, None, sep + explicit_arg + else: + return action, option_string, sep, explicit_arg # search through all possible prefixes of the option string # and all actions in the parser for possible interpretations diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 138ff19e86acf4..9811315ee5c782 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -313,6 +313,7 @@ class TestOptionalsSingleDash(ParserTestCase): ('', NS(x=None)), ('-x a', NS(x='a')), ('-xa', NS(x='a')), + ('-x=a', NS(x='=a')), ('-x -1', NS(x='-1')), ('-x-1', NS(x='-1')), ] @@ -334,6 +335,7 @@ class TestOptionalsSingleDashCombined(ParserTestCase): ('-za', NS(x=False, yyy=None, z='a')), ('-z a', NS(x=False, yyy=None, z='a')), ('-xza', NS(x=True, yyy=None, z='a')), + ('-xz=a', NS(x=True, yyy=None, z='=a')), ('-xz a', NS(x=True, yyy=None, z='a')), ('-x -za', NS(x=True, yyy=None, z='a')), ('-x -z a', NS(x=True, yyy=None, z='a')), @@ -348,10 +350,12 @@ class TestOptionalsSingleDashLong(ParserTestCase): """Test an Optional with a multi-character single-dash option string""" argument_signatures = [Sig('-foo')] - failures = ['-foo', 'a', '--foo', '-foo --foo', '-foo -y', '-fooa'] + failures = ['-foo', 'a', '--foo', '-foo --foo', '-foo -y', '-fooa', + '-foa', '-fa', '-fo=a', '-f=a'] successes = [ ('', NS(foo=None)), ('-foo a', NS(foo='a')), + ('-foo=a', NS(foo='a')), ('-foo -1', NS(foo='-1')), ('-fo a', NS(foo='a')), ('-f a', NS(foo='a')), @@ -2263,19 +2267,22 @@ def test_parse_known_args_with_single_dash_option(self): (NS(known=1, new=0), ['-u'])) self.assertEqual(parser.parse_known_args(['-ku']), (NS(known=1, new=0), ['-u'])) - self.assertArgumentParserError(parser.parse_known_args, ['-k=u']) + self.assertEqual(parser.parse_known_args(['-k=u']), + (NS(known=1, new=0), ['-=u'])) self.assertEqual(parser.parse_known_args(['-uk']), (NS(known=0, new=0), ['-uk'])) self.assertEqual(parser.parse_known_args(['-u=k']), (NS(known=0, new=0), ['-u=k'])) self.assertEqual(parser.parse_known_args(['-kunknown']), (NS(known=1, new=0), ['-unknown'])) - self.assertArgumentParserError(parser.parse_known_args, ['-k=unknown']) + self.assertEqual(parser.parse_known_args(['-k=unknown']), + (NS(known=1, new=0), ['-=unknown'])) self.assertEqual(parser.parse_known_args(['-ku=nknown']), (NS(known=1, new=0), ['-u=nknown'])) self.assertEqual(parser.parse_known_args(['-knew']), (NS(known=1, new=1), ['-ew'])) - self.assertArgumentParserError(parser.parse_known_args, ['-kn=ew']) + self.assertEqual(parser.parse_known_args(['-kn=ew']), + (NS(known=1, new=1), ['-=ew'])) self.assertArgumentParserError(parser.parse_known_args, ['-k-new']) self.assertArgumentParserError(parser.parse_known_args, ['-kn-ew']) self.assertEqual(parser.parse_known_args(['-kne-w']), diff --git a/Misc/NEWS.d/next/Library/2024-09-23-15-38-03.gh-issue-124305.7mQPyn.rst b/Misc/NEWS.d/next/Library/2024-09-23-15-38-03.gh-issue-124305.7mQPyn.rst new file mode 100644 index 00000000000000..d5c4028adc629b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-23-15-38-03.gh-issue-124305.7mQPyn.rst @@ -0,0 +1 @@ +:mod:`argparse` no longer eats initial '=' from short option argument.