Skip to content

gh-152060: Fix datetime.fromisoformat() raising AssertionError in pure Python#152061

Open
tonghuaroot wants to merge 1 commit into
python:mainfrom
tonghuaroot:fix-pydatetime-fromisoformat-assertionerror
Open

gh-152060: Fix datetime.fromisoformat() raising AssertionError in pure Python#152061
tonghuaroot wants to merge 1 commit into
python:mainfrom
tonghuaroot:fix-pydatetime-fromisoformat-assertionerror

Conversation

@tonghuaroot

@tonghuaroot tonghuaroot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #152060.

_pydatetime._parse_isoformat_date() asserted that the date portion has length 7, 8 or
10. For some malformed inputs (e.g. '2020-2020', '2020-1234') the separator finder
yields a 9-character date portion, so the assert fires and a bare AssertionError escapes
datetime.fromisoformat(), which is documented to raise only ValueError. The C
accelerator already raises ValueError. Because the check is an assert, the input also
raises ValueError instead under python -O, so the behaviour differed by build flag.

This replaces the assert with an explicit ValueError whose message matches the C
implementation, so both implementations agree on every build. This is the sibling assert
site to the one fixed in #151771 (gh-151770).

date.fromisoformat() already validates the length before calling
_parse_isoformat_date(), so it is unaffected.

A regression test is added to test_fromisoformat_fails_datetime, which runs under both
the C (_Fast) and pure-Python (_Pure) test classes.

…in pure Python

_pydatetime._parse_isoformat_date() asserted the date portion length, leaking
a bare AssertionError out of datetime.fromisoformat() for some malformed
strings (e.g. '2020-2020'), and behaving differently under -O. The C
accelerator already raises ValueError. Replace the assert with an explicit
ValueError so both implementations agree on all builds.
Comment thread Lib/_pydatetime.py
# see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
assert len(dtstr) in (7, 8, 10)
if len(dtstr) not in (7, 8, 10):
raise ValueError(f"Invalid isoformat string: {dtstr!r}")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{dtstr!r} won't match the C impl, but it doesn’t matter as fromisoformat re-raises anyway.

Suggested change
raise ValueError(f"Invalid isoformat string: {dtstr!r}")
raise ValueError(f"Invalid isoformat string")

'2009-04-19T12:30:45-00:90:00', # Time zone field out from range
'2009-04-19T12:30:45-00:00:90', # Time zone field out from range
'2020-2020', # Ambiguous 9-char date portion
'2020-1234', # Ambiguous 9-char date portion

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'2020-1234', # Ambiguous 9-char date portion

These cases are identical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

datetime.fromisoformat() raises AssertionError instead of ValueError in the pure-Python implementation

2 participants