Skip to content

gh-160665: Recognize dataclass markers deferred by lazy imports - #160668

Open
LarryHu0217 wants to merge 3 commits into
python:mainfrom
LarryHu0217:codex/dataclass-lazy-initvar-160665
Open

LarryHu0217 wants to merge 3 commits into
python:mainfrom
LarryHu0217:codex/dataclass-lazy-initvar-160665

Conversation

@LarryHu0217

@LarryHu0217 LarryHu0217 commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #160665.

Preserve partially resolved annotations when a lazy import cannot be resolved. In annotationlib's FORWARDREF format, resolve lazy imports on name lookup and treat a failed resolution like an undefined name. This keeps known outer types such as list, InitVar and ClassVar intact, with a ForwardRef for the unresolved inner name.

Remove the dataclasses annotation-prefix workaround from the earlier revision. Keep the circular-import regressions for direct, qualified and aliased InitVar, ClassVar and ordinary deferred fields. The InitVar assertions now verify an actual InitVar holding the inner ForwardRef.

Add direct annotationlib regressions for module, class and function annotations, nested containers, successful lazy imports, undefined names and explicit ForwardRef evaluation with globals or locals. Check that VALUE-format errors and STRING-format output remain unchanged, and that an unused lazy import is not loaded. Update the Library NEWS entry.

Validation on macOS arm64 with the existing CPython 3.16.0a1+dev debug interpreter built at dc28c3a358221b1e0ae5f926b72e112cbd1d03f7:

  • Against unchanged upstream annotationlib, the direct regressions fail in five subcases while the unused-import control passes. The dataclass regression has three InitVar errors and one ClassVar failure; the ordinary-field control passes. All cases pass with the underlying fix and unchanged upstream dataclasses implementation.
  • Complete test_dataclasses, test_annotationlib, test_typing, test_lazy_import and test_inspect, with --fail-env-changed -u cpu, strict warning/bytes flags and ignored Python environment variables: all five succeed in both normal mode and -X lazy_imports=all; each run reports 1,711 tests and one skip.
  • All four regression/control methods pass in three fresh processes per mode. Filtered -R 3:3 succeeds in both modes, with no positive leaks in the three measured repetitions.
  • Existing Ruff 0.15.22 with the original root, stdlib and test configurations, the unmodified upstream patchcheck script and staged/unstaged diff checks pass. Committed source hashes match the tested files.

The annotationlib and dataclasses sources and their owning test files match main 32fe0cca23d9e9677107abe4d701cb20768c7926 checked before committing. Tests used an isolated sparse worktree and a source-path overlay for the existing interpreter. Patchcheck only had its source-directory selection pointed to that worktree. Related suites ran at the cached validation baseline; later native changes, the entire CPython suite, native Windows, the documentation build and full hook runner were not validated locally. Ruff retains its Python 3.15 support warning; the hook pins 0.15.17. An initial Ruff attempt omitted the original stdlib configuration from the sparse worktree; materializing that exact configuration resolved the unrelated diagnostics without changing rules or sources.

This addresses unresolved lazy imports, not general missing attributes on eagerly imported, partially initialized modules. No fetch, dependency installation, new environment or native build was performed for this revision.

Resolve the complete circular from-import before defining A so lazy_imports=all exercises unresolved annotations as in normal mode. Keep the strict ForwardRef and classification assertions unchanged.
@DavidCEllis

Copy link
Copy Markdown
Contributor

dataclasses should not be handling PEP-649/749 annotations as if they are string annotations. This should be resolved by better handling of non-resolving lazy imports by annotationlib.

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.

Lazy imports break dataclass InitVars in extremely rare scenarios

2 participants