Skip to content

Fix indefinite hang on OpenAPI schemas with cyclic model dependencies#3078

Open
kevin-paulson-mindbridge-ai wants to merge 4 commits intokoxudaxi:mainfrom
kevin-paulson-mindbridge-ai:slow_schema_generation_fix
Open

Fix indefinite hang on OpenAPI schemas with cyclic model dependencies#3078
kevin-paulson-mindbridge-ai wants to merge 4 commits intokoxudaxi:mainfrom
kevin-paulson-mindbridge-ai:slow_schema_generation_fix

Conversation

@kevin-paulson-mindbridge-ai
Copy link
Copy Markdown
Contributor

@kevin-paulson-mindbridge-ai kevin-paulson-mindbridge-ai commented Apr 10, 2026

We've been generating a model with the tool based on our OpenAPI schema, however since version 0.37.0 we've been unsuccessful in doing so. In the latest release (0.56.0) the generation was revealed to be stuck in sort_data_models. I waited up to an hour, I don't think it was ever going to complete. With this change it now works as expected.

I tried to follow https://datamodel-code-generator.koxudaxi.dev/development-contributing/ as best as I can, but let me know if you would like me to make any changes or if I should create an issue or anything else. Thanks!

Summary by CodeRabbit

  • Bug Fixes

    • Prevented infinite/oscillating ordering when models have circular base-class dependencies during sorting.
    • Added a safety check to skip base-class entries that lack a reference when deriving discriminator mappings, avoiding invalid dereferences.
  • Tests

    • Added tests covering circular base-class dependency handling to ensure sorting stability.
    • Added tests for discriminator mapping behavior when base-class references are missing.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bbe585ad-97cc-49f3-ae3d-fcbf6797410a

📥 Commits

Reviewing files that changed from the base of the PR and between b4e675c and 7eaf6ab.

📒 Files selected for processing (1)
  • tests/parser/test_base.py
✅ Files skipped from review due to trivial changes (1)
  • tests/parser/test_base.py

📝 Walkthrough

Walkthrough

Bug fixes in the parser's base module prevent infinite loops when sorting circular base-class dependencies and add a guard to skip discriminator base classes without references. Two new tests validate stable sorting and safe discriminator handling without dereferencing missing references.

Changes

Cohort / File(s) Summary
Base Parser Logic Fixes
src/datamodel_code_generator/parser/base.py
Added PLR0914 to the noqa directive. In sort_data_models, introduced seen_orders: set[tuple[str, ...]] to detect repeated ordering states and break to avoid infinite/oscillating loops; set unresolved_references to the newly computed list when a repeat is detected. In discriminator handling, skip base classes whose reference is falsy before calling check_paths.
Parser Test Coverage
tests/parser/test_base.py
Added test_sort_data_models_circular_base_classes_no_infinite_loop to ensure mutually-referencing base classes produce a stable order and avoid infinite loops. Added test_apply_discriminator_type_skips_base_class_without_reference to ensure discriminator mapping ignores base-class slots without a Reference and preserves list identity/ordering.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through loops that spun and twined,
Now I pause when orders are aligned.
I skip the gaps where references lack,
And tip my whiskers — no more backtrack! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly summarizes the main fix: preventing indefinite hangs caused by cyclic model dependencies in the sort_data_models function.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 10, 2026

Merging this PR will improve performance by 14.9%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 10 improved benchmarks
✅ 1 untouched benchmark
⏩ 98 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime test_perf_aws_style_openapi_pydantic_v2 1.9 s 1.7 s +11.38%
WallTime test_perf_all_options_enabled 6.7 s 5.9 s +12.08%
WallTime test_perf_graphql_style_pydantic_v2 837 ms 756.3 ms +10.68%
WallTime test_perf_deep_nested 6.2 s 5.5 s +12.99%
WallTime test_perf_complex_refs 2.2 s 1.9 s +14.02%
WallTime test_perf_duplicate_names 1,062.9 ms 946.1 ms +12.34%
WallTime test_perf_large_models_pydantic_v2 3.8 s 3.3 s +14.9%
WallTime test_perf_multiple_files_input 3.8 s 3.4 s +12.38%
WallTime test_perf_kubernetes_style_pydantic_v2 2.7 s 2.4 s +10.25%
WallTime test_perf_openapi_large 3 s 2.7 s +10.42%

Comparing kevin-paulson-mindbridge-ai:slow_schema_generation_fix (7eaf6ab) with main (05901ff)

Open in CodSpeed

Footnotes

  1. 98 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/parser/test_base.py (1)

270-303: Consider asserting a postcondition, not just “no exception.”

This catches the crash, but it would be a bit stronger if it also pinned one observable outcome after __apply_discriminator_type() runs, so a future silent no-op doesn’t still pass.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/parser/test_base.py` around lines 270 - 303, The test currently only
ensures no exception is raised; add a concrete postcondition after calling
parser._Parser__apply_discriminator_type to ensure the union was not silently
modified by the discriminator logic: e.g., assert that union_inner still
contains exactly the two members referencing ref_pet and ref_other (check
identities of union_inner.data_types entries or their .reference attributes) and
that pet_model.base_classes remains unchanged — locate this in
test_apply_discriminator_type_skips_base_class_without_reference and add the
assertion(s) after the call to parser._Parser__apply_discriminator_type([root],
Imports()).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/parser/test_base.py`:
- Around line 270-303: The test currently only ensures no exception is raised;
add a concrete postcondition after calling
parser._Parser__apply_discriminator_type to ensure the union was not silently
modified by the discriminator logic: e.g., assert that union_inner still
contains exactly the two members referencing ref_pet and ref_other (check
identities of union_inner.data_types entries or their .reference attributes) and
that pet_model.base_classes remains unchanged — locate this in
test_apply_discriminator_type_skips_base_class_without_reference and add the
assertion(s) after the call to parser._Parser__apply_discriminator_type([root],
Imports()).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af656bb8-01d5-4471-9440-e33695a9c92c

📥 Commits

Reviewing files that changed from the base of the PR and between 05901ff and b4e675c.

📒 Files selected for processing (2)
  • src/datamodel_code_generator/parser/base.py
  • tests/parser/test_base.py

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (05901ff) to head (7eaf6ab).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #3078   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           87        87           
  Lines        18247     18290   +43     
  Branches      2087      2089    +2     
=========================================
+ Hits         18247     18290   +43     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Collaborator

@ilovelinux ilovelinux left a comment

Choose a reason for hiding this comment

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

This PR implements cycle detection as it is usually done in graph algorithms (BFS, DFS, etc...).

LGTM! Thank you @kevin-paulson-mindbridge-ai 🙂

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.

2 participants