Skip to content

Fix hostname format with field_constraints to use Field(pattern=...)#2724

Merged
koxudaxi merged 3 commits intomainfrom
fix-hostname-field-constraints
Dec 21, 2025
Merged

Fix hostname format with field_constraints to use Field(pattern=...)#2724
koxudaxi merged 3 commits intomainfrom
fix-hostname-field-constraints

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 21, 2025

Fixes: #1972

Summary by CodeRabbit

  • New Features

    • Added hostname validation using a standardized regex; generated models enforce hostname format (field and root types) and support strict-string variants when constraints enabled.
    • Constraint propagation now applies across alternative/multiple-type schemas so hostname patterns are retained in unions.
  • Tests

    • Added tests covering hostname field/root/multiple-type scenarios for Pydantic v1 and v2, including strict-type and field-constraints cases.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 21, 2025

Walkthrough

Adds a HOSTNAME_REGEX constant and exposes it on DataTypeManager across type modules; extends DataTypeManager.get_data_type with a keyword-only field_constraints flag; and threads field_constraints through the JSON Schema parser to inject hostname pattern constraints into generated types and tests.

Changes

Cohort / File(s) Summary
Core type system
src/datamodel_code_generator/model/types.py, src/datamodel_code_generator/model/pydantic/types.py, src/datamodel_code_generator/model/pydantic_v2/types.py
Add module-level HOSTNAME_REGEX and a HOSTNAME_REGEX: ClassVar[str] attribute on DataTypeManager. Extend DataTypeManager.get_data_type(..., *, field_constraints: bool = False, ...) to accept a field_constraints flag.
JSON Schema parser
src/datamodel_code_generator/parser/jsonschema.py
Thread field_constraints through data-type resolution paths and inject hostname pattern constraint (HOSTNAME_REGEX) for fields with "format": "hostname" (object fields, root types, multiple-type branches).
Tests — inputs & expected outputs
tests/data/jsonschema/hostname_field_constraints.json, tests/data/jsonschema/hostname_multiple_types.json, tests/data/jsonschema/hostname_root_type.json, tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v2.py, tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v1.py, tests/data/expected/main/jsonschema/hostname_field_constraints_strict_pydantic_v1.py, tests/data/expected/main/jsonschema/hostname_multiple_types_pydantic_v2.py, tests/data/expected/main/jsonschema/hostname_root_type_pydantic_v2.py, tests/data/expected/main/openapi/pattern/msgspec_pattern.py
Add JSON Schema fixtures for hostname cases and expected generated model files showing hostname validation via Field(pattern=...) (pydantic v2) or Field(regex=...) / StrictStr (v1), and update msgspec pattern output to use Annotated(..., Meta(pattern=...)).
Test suite
tests/main/jsonschema/test_main_jsonschema.py
Add multiple tests exercising hostname handling across pydantic v1/v2, field-constraints flag, strict-types option, root types, and multiple-type schemas.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review constraint propagation in src/datamodel_code_generator/parser/jsonschema.py for all branches (root, object properties, anyOf/allOf/oneOf) to ensure field_constraints is carried and merged correctly.
  • Verify all call sites of get_data_type still match the updated signature and that keyword-only field_constraints does not break subclass or external calls.
  • Confirm HOSTNAME_REGEX is identical and consistently used across the three type modules and that export as ClassVar is type-correct.
  • Validate tests and expected files for correct pydantic v2 Field(pattern=...) vs pydantic v1 Field(regex=...) / StrictStr behavior.

Possibly related PRs

Suggested labels

safe-to-fix

Suggested reviewers

  • ilovelinux

Poem

🐰 I hopped through regex fields all day,
A hostname pattern found its way,
From module constant to DataType land,
Constraints now travel hand in hand.
Hooray — the validator’s bright bouquet!

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 PR title 'Fix hostname format with field_constraints to use Field(pattern=...)' directly addresses the main objective from issue #1972, which is to fix hostname field generation with field_constraints in Pydantic v2.
Linked Issues check ✅ Passed The code changes across all modified files successfully implement the fix for issue #1972. The PR adds HOSTNAME_REGEX constants, integrates field_constraints parameter throughout the type system, updates JsonSchema parser to inject hostname patterns when field_constraints is enabled, and provides comprehensive test coverage for both Pydantic v1 and v2 with various scenarios.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the hostname format handling with field_constraints. Expected files are updated (types.py modules, jsonschema parser, test files) and no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 94.74% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-hostname-field-constraints

📜 Recent 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 1aec6d5 and d031f64.

📒 Files selected for processing (8)
  • src/datamodel_code_generator/model/pydantic/types.py (3 hunks)
  • tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v1.py (1 hunks)
  • tests/data/expected/main/jsonschema/hostname_field_constraints_strict_pydantic_v1.py (1 hunks)
  • tests/data/expected/main/jsonschema/hostname_multiple_types_pydantic_v2.py (1 hunks)
  • tests/data/expected/main/jsonschema/hostname_root_type_pydantic_v2.py (1 hunks)
  • tests/data/jsonschema/hostname_multiple_types.json (1 hunks)
  • tests/data/jsonschema/hostname_root_type.json (1 hunks)
  • tests/main/jsonschema/test_main_jsonschema.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/main/jsonschema/test_main_jsonschema.py
🧰 Additional context used
🧬 Code graph analysis (4)
src/datamodel_code_generator/model/pydantic/types.py (2)
src/datamodel_code_generator/model/types.py (1)
  • DataTypeManager (71-115)
src/datamodel_code_generator/types.py (3)
  • DataTypeManager (788-863)
  • Types (749-785)
  • StrictTypes (101-108)
tests/data/expected/main/jsonschema/hostname_field_constraints_strict_pydantic_v1.py (2)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
  • Field (6-7)
tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v1.py (1)
  • Server (10-14)
tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v1.py (2)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
  • Field (6-7)
tests/data/expected/main/jsonschema/hostname_field_constraints_strict_pydantic_v1.py (1)
  • Server (10-14)
tests/data/expected/main/jsonschema/hostname_root_type_pydantic_v2.py (1)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
  • Field (6-7)
⏰ 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). (10)
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: Analyze (python)
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: benchmarks
🔇 Additional comments (8)
tests/data/jsonschema/hostname_root_type.json (1)

1-6: LGTM!

The JSON schema test fixture is valid and provides a minimal test case for hostname format at the root level.

tests/data/expected/main/jsonschema/hostname_root_type_pydantic_v2.py (1)

10-15: LGTM!

The generated model correctly uses Field(pattern=...) for hostname validation in Pydantic v2, which is the fix objective. The pattern correctly uses $ anchor (as opposed to \Z for v1).

src/datamodel_code_generator/model/pydantic/types.py (2)

161-164: LGTM!

The HOSTNAME_REGEX constant correctly uses the \Z anchor for Pydantic v1, as noted in the comment. This avoids matching trailing newlines that $ would match in Python's regex.


340-365: [Your rewritten review comment text here]
[Exactly ONE classification tag]

tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v1.py (1)

10-14: LGTM!

The generated model correctly uses Field(regex=...) for hostname validation in Pydantic v1 (instead of constr(...)), which is the fix objective. The pattern correctly uses the \Z anchor for v1.

tests/data/jsonschema/hostname_multiple_types.json (1)

1-11: LGTM!

This test fixture covers the edge case where a schema can be either an object or a hostname-formatted string, which is useful for testing union type handling with hostname constraints.

tests/data/expected/main/jsonschema/hostname_field_constraints_strict_pydantic_v1.py (1)

1-14: LGTM!

This expected output file correctly demonstrates the fix for hostname field constraints in Pydantic v1 strict mode. The use of Field(regex=...) instead of constr(...) aligns with the PR objective, and regex= is the correct parameter name for Pydantic v1.

tests/data/expected/main/jsonschema/hostname_multiple_types_pydantic_v2.py (1)

14-28: No anchor inconsistency found. The constr() patterns and Field(pattern=...) all use $ as the end anchor, not a mix of $ and \Z. The escaping differences (raw strings vs. regular strings) are expected in auto-generated output.

Likely an incorrect or invalid review comment.


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.

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: 1

📜 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 3aeaed6 and 1aec6d5.

📒 Files selected for processing (9)
  • src/datamodel_code_generator/model/pydantic/types.py (3 hunks)
  • src/datamodel_code_generator/model/pydantic_v2/types.py (2 hunks)
  • src/datamodel_code_generator/model/types.py (4 hunks)
  • src/datamodel_code_generator/parser/jsonschema.py (4 hunks)
  • src/datamodel_code_generator/types.py (1 hunks)
  • tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v2.py (1 hunks)
  • tests/data/expected/main/openapi/pattern/msgspec_pattern.py (1 hunks)
  • tests/data/jsonschema/hostname_field_constraints.json (1 hunks)
  • tests/main/jsonschema/test_main_jsonschema.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/main/jsonschema/test_main_jsonschema.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)
src/datamodel_code_generator/model/pydantic/types.py (6)
src/datamodel_code_generator/model/pydantic_v2/types.py (1)
  • DataTypeManager (66-149)
src/datamodel_code_generator/model/types.py (1)
  • DataTypeManager (71-115)
src/datamodel_code_generator/types.py (3)
  • DataTypeManager (788-863)
  • Types (749-785)
  • StrictTypes (101-108)
src/datamodel_code_generator/model/dataclass.py (1)
  • DataTypeManager (205-251)
src/datamodel_code_generator/model/msgspec.py (1)
  • DataTypeManager (440-486)
src/datamodel_code_generator/parser/base.py (1)
  • data_type (980-982)
⏰ 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). (8)
  • GitHub Check: benchmarks
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: 3.12 on Windows
🔇 Additional comments (16)
tests/data/expected/main/openapi/pattern/msgspec_pattern.py (1)

13-21: LGTM!

The hostname field now correctly uses Annotated[str, Meta(pattern=...)] with the hostname regex pattern, consistent with the other pattern-constrained fields in this model.

src/datamodel_code_generator/parser/jsonschema.py (4)

1021-1022: LGTM!

The hostname pattern injection is correctly placed after the constraints dict is created and before field creation. The conditions properly guard the injection to only apply when field_constraints is enabled and the format is "hostname".


1067-1072: LGTM!

The field_constraints parameter is correctly propagated to the data type manager, enabling format-aware type resolution when field constraints mode is active.


2584-2586: LGTM!

The hostname pattern injection in parse_root_type mirrors the logic in get_object_field, ensuring consistent behavior across both object field and root type parsing paths.


2649-2659: LGTM!

The hostname constraint handling in _parse_multiple_types_with_properties maintains consistency with the other parsing paths.

src/datamodel_code_generator/types.py (1)

794-798: LGTM!

The HOSTNAME_REGEX class variable provides a centralized hostname validation pattern for the base DataTypeManager. This enables consistent hostname validation across different model backends while allowing subclasses to override if needed.

tests/data/jsonschema/hostname_field_constraints.json (1)

1-11: LGTM!

A clean, minimal test schema that properly exercises the hostname format field constraint feature. The structure follows JSON Schema draft-07 conventions.

src/datamodel_code_generator/model/pydantic_v2/types.py (2)

32-36: LGTM!

The module-level HOSTNAME_REGEX constant is correctly defined with the standard hostname validation pattern.


70-70: LGTM!

The class attribute correctly exposes the hostname regex pattern, enabling the parser to access it through the data type manager.

tests/main/jsonschema/test_main_jsonschema.py (1)

1678-1688: LGTM!

The test follows the established patterns in this test file and properly validates the fix for issue #1972. It correctly tests that hostname format fields use Field(pattern=) instead of constr when --field-constraints is enabled with Pydantic v2.

tests/data/expected/main/jsonschema/hostname_field_constraints_pydantic_v2.py (1)

1-14: LGTM!

The expected output correctly demonstrates the fix for issue #1972. The myhost field now uses Field(pattern=...) instead of constr(...) when --field-constraints is enabled with Pydantic v2, which is the intended behavior.

src/datamodel_code_generator/model/pydantic/types.py (2)

161-164: LGTM - HOSTNAME_REGEX constant for Pydantic v1.

The \Z end anchor is appropriate for Pydantic v1's regex validation, which uses Python's re module directly. This is consistent with the existing pattern at line 106.


340-365: LGTM - Hostname handling with field_constraints.

The logic correctly returns a plain str type (or StrictStr if strict mode is enabled) when field_constraints=True for hostname fields. This allows the JSON Schema parser to attach the hostname regex pattern via Field(pattern=...) instead of using constr(...).

src/datamodel_code_generator/model/types.py (3)

8-8: LGTM - Import update.

The ClassVar import is correctly added to support the new class attribute annotation.


74-75: LGTM - Class attribute exposed.

The HOSTNAME_REGEX is correctly exposed as a class variable, allowing access via DataTypeManager.HOSTNAME_REGEX for use in the JSON Schema parser.


107-115: LGTM - Interface updated with field_constraints parameter.

The field_constraints parameter is correctly added as a keyword-only argument with a default value of False. The ARG002 noqa comment appropriately indicates the parameter is intentionally unused in this base implementation, establishing the interface for subclasses to override.

Comment thread src/datamodel_code_generator/model/types.py
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.35%. Comparing base (3aeaed6) to head (d031f64).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2724   +/-   ##
=======================================
  Coverage   99.35%   99.35%           
=======================================
  Files          83       83           
  Lines       11838    11868   +30     
  Branches     1428     1433    +5     
=======================================
+ Hits        11762    11792   +30     
  Misses         45       45           
  Partials       31       31           
Flag Coverage Δ
unittests 99.35% <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.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 21, 2025

CodSpeed Performance Report

Merging #2724 will not alter performance

Comparing fix-hostname-field-constraints (d031f64) with main (3aeaed6)

Summary

✅ 70 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.

@koxudaxi koxudaxi merged commit 8a10962 into main Dec 21, 2025
38 checks passed
@koxudaxi koxudaxi deleted the fix-hostname-field-constraints branch December 21, 2025 08:10
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.

hostname string always generated with constr with pydantic2

1 participant