https://github.com/python/cpython/commit/8f26a79b3322d29ad603662c2b01109f2a719506 commit: 8f26a79b3322d29ad603662c2b01109f2a719506 branch: 3.12 author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com> committer: vstinner <vstin...@python.org> date: 2025-03-11T12:00:06Z summary:
gh-130959: Reject whitespace in fractions, in pure Python `fromisoformat()` (GH-130962) (GH-131076) (#131086) Fix the pure Python implementation of `fromisoformat()` to reject any non-digit characters, including whitespace, in the fractional part of time specification. This makes the behavior consistent with the C implementation, and prevents incorrect parsing of these fractions (e.g. `.400 ` would be misinterpreted as `.04`). (cherry picked from commit 33494b4d0dafc34ff4f1c118b7b3b5d8de3dd0f4) (cherry picked from commit 27fd328cf68e5d812cdb7f9533a16dd68d911c54) Co-authored-by: Victor Stinner <vstin...@python.org> Co-authored-by: Michał Górny <mgo...@gentoo.org> files: A Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst M Lib/_pydatetime.py M Lib/test/datetimetester.py diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index fc43cf0bba32da..6e9c3a9b8364bb 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -402,6 +402,8 @@ def _parse_hh_mm_ss_ff(tstr): raise ValueError("Invalid microsecond component") else: pos += 1 + if not all(map(_is_ascii_digit, tstr[pos:])): + raise ValueError("Non-digit values in fraction") len_remainder = len_str - pos @@ -413,9 +415,6 @@ def _parse_hh_mm_ss_ff(tstr): time_comps[3] = int(tstr[pos:(pos+to_parse)]) if to_parse < 6: time_comps[3] *= _FRACTION_CORRECTION[to_parse-1] - if (len_remainder > to_parse - and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))): - raise ValueError("Non-digit values in unparsed fraction") return time_comps diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 903a43aad81994..42a505be1d93f0 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3325,6 +3325,9 @@ def test_fromisoformat_fails_datetime(self): '2009-04-19T12:30:45.123456-05:00a', # Extra text '2009-04-19T12:30:45.123-05:00a', # Extra text '2009-04-19T12:30:45-05:00a', # Extra text + '2009-04-19T12:30:45.400 +02:30', # Space between ms and timezone (gh-130959) + '2009-04-19T12:30:45.400 ', # Trailing space (gh-130959) + '2009-04-19T12:30:45. 400', # Space before fraction (gh-130959) ] for bad_str in bad_strs: @@ -4377,6 +4380,9 @@ def test_fromisoformat_fails(self): '12:30:45.123456-', # Extra at end of microsecond time '12:30:45.123456+', # Extra at end of microsecond time '12:30:45.123456+12:00:30a', # Extra at end of full time + '12:30:45.400 +02:30', # Space between ms and timezone (gh-130959) + '12:30:45.400 ', # Trailing space (gh-130959) + '12:30:45. 400', # Space before fraction (gh-130959) ] for bad_str in bad_strs: diff --git a/Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst b/Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst new file mode 100644 index 00000000000000..85f61ca43b2580 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst @@ -0,0 +1,3 @@ +Fix pure-Python implementation of :func:`datetime.time.fromisoformat` to reject +times with spaces in fractional part (for example, ``12:34:56.400 +02:00``), +matching the C implementation. Patch by Michał Gorny. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com