Skip to content

Propagate errors from typing.ClassVar attribute lookup (#1221) - #1223

Open
charan-rathore wants to merge 2 commits into
msgspec:mainfrom
charan-rathore:fix-1221-classvar-lookup-error
Open

charan-rathore wants to merge 2 commits into
msgspec:mainfrom
charan-rathore:fix-1221-classvar-lookup-error

Conversation

@charan-rathore

@charan-rathore charan-rathore commented Oct 1, 2026 •

Copy link
Copy Markdown

Closes #1221

The #1097 fix looks up ClassVar on whatever typing names in the module
namespace, but if that attribute lookup itself raises, the error return is
missed: structmeta_is_classvar compares the NULL result against
typing.ClassVar, reports "not a ClassVar", and returns 0 with the
exception still pending. On CPython builds with assertions enabled this
trips assert(!PyErr_Occurred()) in type_new_init and terminates the
interpreter.

Return -1 when the lookup fails, matching the error handling already used
for the __origin__ lookup just below. The original AttributeError from
#1096 still propagates exactly as before.

Tests: the existing test_wrong_classvar regression is parametrized to also
cover the subscripted form typing.ClassVar[int], and a new test covers a
typing stand-in whose ClassVar attribute raises an arbitrary error, so
the propagation path itself is pinned rather than only the #1096 case.

Verified on a locally built CPython 3.13.7 --with-pydebug: the unpatched
code stops the interpreter in test_wrong_classvar (exit 134); with the
patch the full unit suite passes (6298 passed, 313 skipped). Focused tests
also pass on a regular 3.13 build, which is what CI runs.

Changelog entry included under Unreleased.

Tested on Python 3.13 only (debug and regular builds). CI covers 3.10 to 3.15; the change is a two-line error check in version-independent C.

@Siyet Siyet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you remove the claim that regular builds silently dropped the lookup error? On regular CPython 3.12.13, the original test already raises AttributeError before this change, and the property case also preserves the original RuntimeError. The fix prevents the assertion failure by returning immediately when the lookup fails.

@charan-rathore

Copy link
Copy Markdown
Author

Thanks, you're right. I dropped that sentence from the description. On a regular build the original error still surfaces; the fix is about the assertion failure on debug builds, where returning right away when the lookup fails avoids hitting assert(!PyErr_Occurred()).

Siyet commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Thx, could you also remove that claim from docs/changelog.md? It is still present in the Unreleased entry.

@charan-rathore

Copy link
Copy Markdown
Author

Done, removed it from the changelog entry too (ccc3a24).

This branch had an error being deployed

1 failed deployment
docs-preview — ccc3a249 Deployed Oct 1, 2026 by charan-rathore via Deploy preview #590
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0.22.0 regression: tests/unit/test_struct.py::TestClassVar::test_wrong_classvar is breaking assertions in CPython

2 participants