Skip to content

Respect model-level strict config in synthesized RootModel __init__ - #5649

Open
soaring0616 wants to merge 1 commit into
pyrefly-org:mainfrom
soaring0616:fix-rootmodel-config-strict
Open

soaring0616 wants to merge 1 commit into
pyrefly-org:mainfrom
soaring0616:fix-rootmodel-config-strict

Conversation

@soaring0616

Copy link
Copy Markdown
Contributor

Summary

For a concrete root type (not Any or a type variable), Pyrefly widens the root parameter of the synthesized RootModel.__init__ to Any when strict mode is disabled (pydantic.rs#L165-L169). This allows valid Pydantic runtime coercions (e.g., passing bytes to RootModel[str]) without triggering false positives, preserving root to the concrete type only when strict mode is enabled.

Previously, has_strict was computed in get_pydantic_root_model_type_via_mro (L131-L133), which only captures strictness written on the base class type argument (such as RootModel[StrictInt]), including when inherited from a parent class. As a result, model-level strict=True from model_config or a class keyword was ignored even though it is already resolved into dataclass.kws.strict.

This change takes dataclass.kws.strict into account when synthesizing RootModel.__init__, reusing the dataclass config already available there. This change also adds a test case covering the model_config, class keyword, inherited, and lax cases.

Fixes #5242

  • I am a human, and I fully understand the code I am submitting.

What changed

  • pyrefly/lib/alt/class/dataclass.rs:L156:160: Passed dataclass.kws.strict alongside has_strict when calling get_pydantic_root_model_init.
  • pyrefly/lib/test/pydantic/root_model.rs:L353:373: Added test_root_model_config_strict with test classes covering model_config (class Text), class keyword (class Text2), inherited strictness (class Child), and the default lax behavior (class Lax).

Test Plan

  • cargo test -p pyrefly --lib -- test::pydanticshows test result: ok. 174 passed; 0 failed; 0 ignored in my local machine
    -test_root_model_config_strict to fail with expected 3 errors, but got 0.
  • Full test suite (test.py): On macOS debug builds, test::cycles::deep_phi_chain_term_expr hits a pre-existing stack overflow (reproduced without this change); the suite passes with PYREFLY_STACK_SIZE=33554432.
  • Formatting & lints: cargo fmt --check and cargo clippy pass with no warnings.

AI disclosure

  • I used Claude to study the codebase, provides the possible direction and the test range.
  • I repeatedly test my ideas and confirm the direction, and verify them on my local machine.

@github-actions

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pyrefly's synthesized Pydantic RootModel constructor ignores model-level strict=True

1 participant