diff options
| author | Crowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com> | 2024-01-13 12:02:39 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-13 12:02:39 (GMT) |
| commit | dd56b5748317c3d504d6a9660d9207620c547f5c (patch) | |
| tree | 62da7311e73f41d4377f6138f9413976a20e371b | |
| parent | c7d59bd8cfa053e77ae3446c82afff1fd38a4886 (diff) | |
| download | cpython-dd56b5748317c3d504d6a9660d9207620c547f5c.zip cpython-dd56b5748317c3d504d6a9660d9207620c547f5c.tar.gz cpython-dd56b5748317c3d504d6a9660d9207620c547f5c.tar.bz2 | |
gh-114014: Update `fractions.Fraction()`'s rational parsing regex (#114015)
Fix a bug in the regex used for parsing a string input to the `fractions.Fraction` constructor. That bug led to an inconsistent exception message being given for some inputs.
---------
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
| -rw-r--r-- | Lib/fractions.py | 20 | ||||
| -rw-r--r-- | Lib/test/test_fractions.py | 24 | ||||
| -rw-r--r-- | Misc/NEWS.d/next/Library/2024-01-13-11-34-29.gh-issue-114014.WRHifN.rst | 1 |
3 files changed, 35 insertions, 10 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py index 6532d5d..389ab38 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -55,17 +55,17 @@ def _hash_algorithm(numerator, denominator): return -2 if result == -1 else result _RATIONAL_FORMAT = re.compile(r""" - \A\s* # optional whitespace at the start, - (?P<sign>[-+]?) # an optional sign, then - (?=\d|\.\d) # lookahead for digit or .digit - (?P<num>\d*|\d+(_\d+)*) # numerator (possibly empty) - (?: # followed by - (?:\s*/\s*(?P<denom>\d+(_\d+)*))? # an optional denominator - | # or - (?:\.(?P<decimal>d*|\d+(_\d+)*))? # an optional fractional part - (?:E(?P<exp>[-+]?\d+(_\d+)*))? # and optional exponent + \A\s* # optional whitespace at the start, + (?P<sign>[-+]?) # an optional sign, then + (?=\d|\.\d) # lookahead for digit or .digit + (?P<num>\d*|\d+(_\d+)*) # numerator (possibly empty) + (?: # followed by + (?:\s*/\s*(?P<denom>\d+(_\d+)*))? # an optional denominator + | # or + (?:\.(?P<decimal>\d*|\d+(_\d+)*))? # an optional fractional part + (?:E(?P<exp>[-+]?\d+(_\d+)*))? # and optional exponent ) - \s*\Z # and optional whitespace to finish + \s*\Z # and optional whitespace to finish """, re.VERBOSE | re.IGNORECASE) diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 8477952..af3cb21 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -261,6 +261,30 @@ class FractionTest(unittest.TestCase): self.assertRaisesMessage( ValueError, "Invalid literal for Fraction: '1.1e+1__1'", F, "1.1e+1__1") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '123.dd'", + F, "123.dd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '123.5_dd'", + F, "123.5_dd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: 'dd.5'", + F, "dd.5") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '7_dd'", + F, "7_dd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '1/dd'", + F, "1/dd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '1/123_dd'", + F, "1/123_dd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '789edd'", + F, "789edd") + self.assertRaisesMessage( + ValueError, "Invalid literal for Fraction: '789e2_dd'", + F, "789e2_dd") # Test catastrophic backtracking. val = "9"*50 + "_" self.assertRaisesMessage( diff --git a/Misc/NEWS.d/next/Library/2024-01-13-11-34-29.gh-issue-114014.WRHifN.rst b/Misc/NEWS.d/next/Library/2024-01-13-11-34-29.gh-issue-114014.WRHifN.rst new file mode 100644 index 0000000..a6630d7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-13-11-34-29.gh-issue-114014.WRHifN.rst @@ -0,0 +1 @@ +Fixed a bug in :class:`fractions.Fraction` where an invalid string using ``d`` in the decimals part creates a different error compared to other invalid letters/characters. Patch by Jeremiah Gabriel Pascual. |
