Skip to content

Pass schema extensions to templates#2790

Merged
koxudaxi merged 3 commits intomainfrom
feature/schema-extensions-template
Dec 24, 2025
Merged

Pass schema extensions to templates#2790
koxudaxi merged 3 commits intomainfrom
feature/schema-extensions-template

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 24, 2025

Fixes: #2158

Summary by CodeRabbit

  • New Features

    • Propagates OpenAPI/JSON Schema x-* extensions into generated templates so custom templates can access schema-level metadata (e.g., collection names).
  • Tests

    • Added tests to verify schema extensions are passed through and accessible in custom template generation.
  • Documentation

    • Updated template customization docs with a "Schema Extensions" section and examples showing how to use extensions in templates.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 24, 2025

Warning

Rate limit exceeded

@koxudaxi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 9 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 5ce0cd7 and 628eab7.

📒 Files selected for processing (1)
  • docs/custom_template.md
📝 Walkthrough

Walkthrough

Adds propagation of OpenAPI/JSON Schema x-* extension fields into template extra data by introducing JsonSchemaParser.set_schema_extensions and calling it at multiple parse points so templates can access schema extensions.

Changes

Cohort / File(s) Summary
Parser enhancement
src/datamodel_code_generator/parser/jsonschema.py
Adds set_schema_extensions(self, path: str, obj: JsonSchemaObject) -> None to collect x-* fields from obj.extras and store them at extra_template_data[path]["extensions"]. Calls inserted at many parse locations (objects, references, arrays, enums, root types, variants). Minor type/annotation formatting tweak in parse_root_type.
Generated test data
tests/data/expected/main/openapi/schema_extensions.py
New expected output showing generated Pydantic models (User, Pet) that include class attributes (e.g., __collection__) expected to come from schema extensions.
Tests
tests/main/openapi/test_main_openapi.py
Adds test_main_openapi_schema_extensions (uses custom template dir) to assert that schema extensions are available to templates; includes import alias for model_base. (Note: duplicate test definitions were added in the diff.)
Docs
docs/custom_template.md
Adds a "Schema Extensions" section documenting that x-* fields are exposed to templates via an extensions variable and showing usage examples.

Sequence Diagram(s)

(Skipped — change is confined to parser/template data propagation and does not introduce a multi-component control flow requiring visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I sniffed the schemas, small and sweet,
x-keys tucked in corners, now a treat,
I nudged them gently into templates' view,
Models wear collections and metadata too,
Hop, code, hop — extensions bloom anew! 🌱

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Pass schema extensions to templates' directly and clearly describes the main feature being added in the pull request.
Linked Issues check ✅ Passed The PR implements the exact feature requested in #2158: passing schema extensions (x-*) to templates so they can access custom OpenAPI extensions.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing schema extensions support: core implementation in jsonschema.py, test models, test cases, and documentation updates are all in scope.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.

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.

@koxudaxi koxudaxi force-pushed the feature/schema-extensions-template branch from 4dde7d3 to 8a19cab Compare December 24, 2025 18:22
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.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/datamodel_code_generator/parser/jsonschema.py (1)

2602-2602: Remove unused noqa directive.

Static analysis correctly identifies that the noqa directive for PLR0912 and PLR0915 is unused, as noted in the provided hints.

🔎 Suggested cleanup
-    def parse_root_type(  # noqa: PLR0912, PLR0915
+    def parse_root_type(
tests/main/openapi/test_main_openapi.py (1)

613-635: Consider improving test isolation for cache management.

The explicit cache clearing at lines 617-618 suggests potential test isolation concerns:

  1. Asymmetric cleanup: Caches are cleared before the test but not after, which could affect subsequent tests.
  2. Inconsistency: Other tests in this file don't clear these caches, which may indicate incomplete isolation.
  3. Test order dependency risk: Manual cache management can lead to flaky tests if execution order changes.

Recommendation: Consider using a pytest fixture for cache management to ensure consistent cleanup:

Suggested fixture approach
@pytest.fixture
def clear_template_cache():
    """Clear template caches before and after test to ensure isolation."""
    model_base._get_environment.cache_clear()
    model_base._get_template_with_custom_dir.cache_clear()
    yield
    model_base._get_environment.cache_clear()
    model_base._get_template_with_custom_dir.cache_clear()

Then use it in the test:

def test_main_openapi_schema_extensions(
    capsys: pytest.CaptureFixture, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, clear_template_cache
) -> None:
    """Test that schema extensions (x-* fields) are passed to custom templates."""
    # Cache clearing handled by fixture
    monkeypatch.chdir(tmp_path)
    ...

However, if this manual approach is intentional for this specific test scenario, the current implementation is functionally correct.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f59786f and 8a19cab.

⛔ Files ignored due to path filters (2)
  • tests/data/openapi/schema_extensions.yaml is excluded by !tests/data/**/*.yaml and included by none
  • tests/data/templates_extensions/pydantic_v2/BaseModel.jinja2 is excluded by none and included by none
📒 Files selected for processing (3)
  • src/datamodel_code_generator/parser/jsonschema.py
  • tests/data/expected/main/openapi/schema_extensions.py
  • tests/main/openapi/test_main_openapi.py
🧰 Additional context used
🧬 Code graph analysis (3)
tests/data/expected/main/openapi/schema_extensions.py (1)
src/datamodel_code_generator/model/base.py (1)
  • name (741-743)
src/datamodel_code_generator/parser/jsonschema.py (2)
src/datamodel_code_generator/reference.py (1)
  • reference (76-78)
src/datamodel_code_generator/model/base.py (1)
  • path (822-824)
tests/main/openapi/test_main_openapi.py (4)
src/datamodel_code_generator/model/base.py (2)
  • _get_environment (405-420)
  • _get_template_with_custom_dir (424-436)
src/datamodel_code_generator/__init__.py (1)
  • chdir (154-164)
tests/conftest.py (1)
  • freeze_time (285-288)
tests/main/conftest.py (1)
  • run_main_and_assert (244-408)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/parser/jsonschema.py

2602-2602: Unused noqa directive (non-enabled: PLR0912, PLR0915)

Remove unused noqa directive

(RUF100)

⏰ 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). (9)
  • GitHub Check: benchmarks
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.10 on macOS
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: Analyze (python)
🔇 Additional comments (4)
src/datamodel_code_generator/parser/jsonschema.py (2)

1158-1163: LGTM! Well-designed helper method.

The implementation correctly filters x-* extension fields from obj.extras and stores them in extra_template_data only when extensions exist. This follows the same pattern as other metadata setters in the class and avoids polluting the template data with empty dictionaries.


1010-1010: Excellent coverage of extension propagation points.

The set_schema_extensions calls are well-placed across all major parsing flows (variant models, objects, arrays, enums, root types, and allOf combinations). The consistent pattern of calling with reference.path after reference creation ensures schema extensions are available for all model types.

Also applies to: 1904-1904, 2056-2056, 2110-2110, 2281-2281, 2563-2563, 2664-2664, 2729-2729, 2852-2852, 2925-2925

tests/data/expected/main/openapi/schema_extensions.py (1)

1-19: LGTM! Test fixture demonstrates the feature working correctly.

This expected output validates that schema extensions are successfully passed to templates and used to generate custom model attributes (__collection__). The models are valid Pydantic v2 code and demonstrate a realistic use case for the new feature.

tests/main/openapi/test_main_openapi.py (1)

32-32: LGTM! Import placement is correct.

The import is properly positioned within the datamodel_code_generator imports section and uses a clear alias.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 24, 2025

CodSpeed Performance Report

Merging #2790 will not alter performance

Comparing feature/schema-extensions-template (628eab7) with main (f59786f)

Summary

✅ 73 untouched
⏩ 10 skipped1

Footnotes

  1. 10 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.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.48%. Comparing base (5cceb4f) to head (628eab7).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2790    +/-   ##
========================================
  Coverage   99.47%   99.48%            
========================================
  Files          88       88            
  Lines       13256    13386   +130     
  Branches     1557     1566     +9     
========================================
+ Hits        13187    13317   +130     
  Misses         36       36            
  Partials       33       33            
Flag Coverage Δ
unittests 99.48% <100.00%> (+<0.01%) ⬆️

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

@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.

Actionable comments posted: 0

🧹 Nitpick comments (1)
docs/custom_template.md (1)

86-86: Use Markdown headings instead of bold emphasis for section labels.

Lines 86, 111, 122, and 129 use **bold** formatting for what are effectively subsection labels (file names and command descriptions). To improve document structure and follow Markdown best practices, convert these to proper ### headings.

🔎 Proposed fixes
-**api.yaml**
+### api.yaml

-**custom_templates/pydantic_v2/BaseModel.jinja2**
+### custom_templates/pydantic_v2/BaseModel.jinja2

-**Run the generator**
+### Run the generator

-**Generated Output**
+### Generated Output

This improves document accessibility and consistency, as the earlier "Example: Database Model Configuration" section already uses proper heading levels (lines 82).

Also applies to: 111-111, 122-122, 129-129

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a19cab and 5ce0cd7.

📒 Files selected for processing (1)
  • docs/custom_template.md
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
docs/custom_template.md

86-86: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


111-111: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


122-122: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


129-129: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ 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). (20)
  • GitHub Check: 3.14 on Windows
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: py312-black23 on Ubuntu
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.11 on macOS
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: pkg_meta
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
  • GitHub Check: update-readme
🔇 Additional comments (1)
docs/custom_template.md (1)

78-159: Comprehensive and clear documentation of the schema extensions feature.

The new "Schema Extensions" section effectively communicates the feature with a practical example, clear template access patterns, availability reference table, and use cases. The progression from schema definition → template code → command execution → generated output is well-structured for user understanding.

@koxudaxi koxudaxi enabled auto-merge (squash) December 24, 2025 19:03
@koxudaxi koxudaxi disabled auto-merge December 24, 2025 19:04
Document how x-* schema extensions are passed to custom templates
via the extensions variable, with examples for database model
configuration and other use cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@koxudaxi koxudaxi force-pushed the feature/schema-extensions-template branch from 5ce0cd7 to 628eab7 Compare December 24, 2025 19:05
@koxudaxi koxudaxi enabled auto-merge (squash) December 24, 2025 19:07
@koxudaxi koxudaxi merged commit 602193a into main Dec 24, 2025
36 checks passed
@koxudaxi koxudaxi deleted the feature/schema-extensions-template branch December 24, 2025 19:17
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: This PR adds a new extensions variable to template context containing x-* schema extension fields. The change is purely additive - it makes new data available to templates without modifying existing behavior. Default templates are unchanged and don't use this variable. Existing custom templates will continue to work because: 1) They don't reference the new extensions variable, 2) Jinja2 doesn't fail when unused variables exist in context, 3) No CLI or API changes were made, 4) Generated output from default templates is identical. Users can optionally leverage this new capability in custom templates but are not required to update anything.


This analysis was performed by Claude Code Action

koxudaxi added a commit that referenced this pull request Dec 25, 2025
* Pass schema extensions to templates

* Move model_base import to top of file

* Add schema extensions documentation

Document how x-* schema extensions are passed to custom templates
via the extensions variable, with examples for database model
configuration and other use cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
koxudaxi added a commit that referenced this pull request Dec 25, 2025
* Add --collapse-root-models-name-strategy option

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add pragma no cover for defensive edge cases

* Achieve 100% diff coverage for collapse-root-models-name-strategy

* Use cast instead of type ignore comment

* Remove line comments from collapse-root-models implementation

* Add complex e2e tests for collapse-root-models-name-strategy

* Update reference metadata when renaming in parent strategy

* Refactor collapse-root-models tests to use parameterization for v1/v2

* Add schema path context to error messages (#2786)

* Return str or dict when output=None in generate() (#2787)

* Add --http-timeout CLI option (#2788)

* Add --http-timeout CLI option for configurable HTTP request timeout

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Pass schema extensions to templates (#2790)

* Pass schema extensions to templates

* Move model_base import to top of file

* Add schema extensions documentation

Document how x-* schema extensions are passed to custom templates
via the extensions variable, with examples for database model
configuration and other use cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add propertyNames and x-propertyNames support (#2789)

* Add propertyNames and x-propertyNames support

* Fix Pydantic v1 compatibility for x-propertyNames

Use the model_validate utility function from util module instead of
calling JsonSchemaObject.model_validate() directly, which only
exists in Pydantic v2.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add test for x-propertyNames non-dict branch coverage

Test that x-propertyNames with non-dict value (e.g., boolean) is
correctly ignored, achieving 100% diff coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add support for additional_imports in extra-template-data JSON (#2793)

* Update zensical to 0.0.15 (#2794)

* Add --use-field-description-example option (#2792)

* Add --use-field-description-example option

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add tests for complete branch coverage of docstring property

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix formatting in test file

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

Pass reference to schema (or schema extensions) to templates

1 participant