From f6234ed79d49cb283661d0d1389db3fa2739dd09 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 23 Sep 2024 11:16:55 -0700 Subject: [PATCH 1/3] [3.12] GH-124321: Fix argparse negative number parsing to capture -.5(GH-124322) (cherry picked from commit dc48312717142ec902197da504fad333f13c9937) Co-authored-by: Savannah Ostrowski Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index adf8bdf16f1f5a..08a3155fd16afc 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1405,7 +1405,7 @@ def __init__(self, self._defaults = {} # determines whether an "option" looks like a negative number - self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$') + self._negative_number_matcher = _re.compile(r'^-(?:\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?|\.\d+(?:_\d+)*)$') # whether or not there are any optionals that look like negative # numbers -- uses a list so it can be shared and edited diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 42998d5c6ea06d..c8d120cadb2caf 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2092,6 +2092,49 @@ class TestActionExtend(ParserTestCase): ('--foo f1 --foo f2 f3 f4', NS(foo=['f1', 'f2', 'f3', 'f4'])), ] + +class TestNegativeNumber(ParserTestCase): + """Test parsing negative numbers""" + + argument_signatures = [ + Sig('--int', type=int), + Sig('--float', type=float), + ] + failures = [ + '--float -_.45', + '--float -1__000.0', + '--int -1__000', + ] + successes = [ + ('--int -1000 --float -1000.0', NS(int=-1000, float=-1000.0)), + ('--int -1_000 --float -1_000.0', NS(int=-1000, float=-1000.0)), + ('--int -1_000_000 --float -1_000_000.0', NS(int=-1000000, float=-1000000.0)), + ('--float -1_000.0', NS(int=None, float=-1000.0)), + ('--float -1_000_000.0_0', NS(int=None, float=-1000000.0)), + ('--float -.5', NS(int=None, float=-0.5)), + ('--float -.5_000', NS(int=None, float=-0.5)), + ] + +class TestInvalidAction(TestCase): + """Test invalid user defined Action""" + + class ActionWithoutCall(argparse.Action): + pass + + def test_invalid_type(self): + parser = argparse.ArgumentParser() + + parser.add_argument('--foo', action=self.ActionWithoutCall) + self.assertRaises(NotImplementedError, parser.parse_args, ['--foo', 'bar']) + + def test_modified_invalid_action(self): + parser = ErrorRaisingArgumentParser() + action = parser.add_argument('--foo') + # Someone got crazy and did this + action.type = 1 + self.assertRaises(ArgumentParserError, parser.parse_args, ['--foo', 'bar']) + + # ================ # Subparsers tests # ================ From e066c934c4cb50dfaedd7f04fccef0b3afb9566e Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 23 Sep 2024 11:31:56 -0700 Subject: [PATCH 2/3] Fix up tests --- Lib/test/test_argparse.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c8d120cadb2caf..a5f11f029e6a79 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2115,25 +2115,6 @@ class TestNegativeNumber(ParserTestCase): ('--float -.5_000', NS(int=None, float=-0.5)), ] -class TestInvalidAction(TestCase): - """Test invalid user defined Action""" - - class ActionWithoutCall(argparse.Action): - pass - - def test_invalid_type(self): - parser = argparse.ArgumentParser() - - parser.add_argument('--foo', action=self.ActionWithoutCall) - self.assertRaises(NotImplementedError, parser.parse_args, ['--foo', 'bar']) - - def test_modified_invalid_action(self): - parser = ErrorRaisingArgumentParser() - action = parser.add_argument('--foo') - # Someone got crazy and did this - action.type = 1 - self.assertRaises(ArgumentParserError, parser.parse_args, ['--foo', 'bar']) - # ================ # Subparsers tests From ed91dec9602d25a4e820e11ae6bc22193a48fe2e Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 23 Sep 2024 11:32:27 -0700 Subject: [PATCH 3/3] Remove newline --- Lib/test/test_argparse.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index a5f11f029e6a79..67f1064b0c3b18 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2115,7 +2115,6 @@ class TestNegativeNumber(ParserTestCase): ('--float -.5_000', NS(int=None, float=-0.5)), ] - # ================ # Subparsers tests # ================