Add model_rebuild for models with typing imports when using deferred annotations#2725
Add model_rebuild for models with typing imports when using deferred annotations#2725
Conversation
…annotations 🤖 Generated with [Claude Code](https://claude.com/claude-code)
WalkthroughAdds a typing-import rebuild heuristic: introduces a TYPING_IMPORTS_REQUIRING_REBUILD constant, extends exported typing IMPORT_* symbols, and updates resolve-reference logic to compute and merge typing-related import paths so modules with deferred annotations trigger model_rebuild when needed. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…-typing-imports # Conflicts: # tests/main/openapi/test_main_openapi.py
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2725 +/- ##
=======================================
Coverage 99.35% 99.35%
=======================================
Files 83 83
Lines 11868 11874 +6
Branches 1433 1434 +1
=======================================
+ Hits 11792 11798 +6
Misses 45 45
Partials 31 31
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/datamodel_code_generator/parser/base.py (2)
43-57: Typing import constants andTYPING_IMPORTS_REQUIRING_REBUILDgrouping look consistentGrouping
IMPORT_DICT,IMPORT_FROZEN_SET,IMPORT_LIST,IMPORT_MAPPING,IMPORT_OPTIONAL,IMPORT_SEQUENCE,IMPORT_SET,IMPORT_TUPLE, andIMPORT_UNIONintoTYPING_IMPORTS_REQUIRING_REBUILDmatches howDataType.importsyields typing/container imports, so the later membership checks over field imports will behave as intended. If this list ever diverges fromDataType.imports, a short comment referencing that coupling here could help future maintainers keep them in sync, but the current setup looks correct and self-contained.Also applies to: 109-119
2398-2441: Deferred-annotation rebuild now correctly considers typing imports; consider seeding inheritance with themThe extended block in
__get_resolve_reference_action_parts:
- Restricts the new behavior to deferred-annotation scenarios using the v2 resolver.
- Detects
typing_import_pathsby scanning each model’s field imports forTYPING_IMPORTS_REQUIRING_REBUILD.- Unions these paths into
required_paths_in_module, then computesforward_neededbased on intra-module references and propagates along base-class relationships.- Ensures all models with relevant typing imports end up in
required_paths_in_modulevia the finalrequired_filtered | typing_import_pathsunion.This is a good fit for the PR’s goal: modules whose fields depend on typing-based imports under deferred annotations will now also emit
model_rebuild()calls.One optional hardening you might consider: if you want subclasses of typing-heavy models to always participate in the inheritance propagation, you could seed
required_filteredwithtyping_import_pathsas well, not just withforward_needed. That would look like:Suggested tweak to seed inheritance propagation with typing imports
- changed = True - required_filtered = set(forward_needed) + changed = True + # Seed with forward-needed models and those with typing imports, + # so subclasses of typing-heavy bases are also pulled in. + required_filtered = set(forward_needed) | typing_import_paths @@ - required_paths_in_module = required_filtered | typing_import_paths + required_paths_in_module = required_filteredThis change is conservative (it can only increase the set of models that get
model_rebuild()calls) and may further reduce the risk of subtle inheritance edge cases, but the current logic is already a clear improvement and should address the reported regression.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/parser/base.py(3 hunks)tests/main/openapi/test_main_openapi.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/datamodel_code_generator/parser/base.py (4)
src/datamodel_code_generator/imports.py (1)
Import(20-38)src/datamodel_code_generator/model/base.py (3)
path(716-718)imports(281-300)imports(635-640)src/datamodel_code_generator/types.py (1)
imports(450-495)src/datamodel_code_generator/model/typed_dict.py (1)
imports(150-155)
tests/main/openapi/test_main_openapi.py (2)
tests/main/conftest.py (2)
output_file(98-100)run_main_and_assert(244-408)tests/test_main_kr.py (1)
output_file(44-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (1)
tests/main/openapi/test_main_openapi.py (1)
4400-4409: New OpenAPI regression test is well-wired and aligned with the fixThe
test_main_openapi_typing_imports_rebuildtest follows the existingrun_main_and_assertpattern, uses the newtyping_imports_rebuild.yaml/.pyfixtures, and targetspydantic_v2.BaseModelwith--no-use-union-operator, which is exactly the scenario this PR is addressing. No changes needed here.
CodSpeed Performance ReportMerging #2725 will not alter performanceComparing Summary
Footnotes
|
Fixes: #2341
Summary by CodeRabbit
Improvements
New Output
Tests
✏️ Tip: You can customize this high-level summary in your review settings.