Fix regex_engine config not applied to RootModel generic#2721
Conversation
WalkthroughDetects regex lookaround patterns to enable Pydantic v2's python regex engine; adds base_type_hint computation for unconstrained RootModel generics; updates RootModel template and Pydantic v2 base_model lookup; adds JSON Schema fixtures/tests for lookaround scenarios and removes/adjusts some test lint comments and formatting. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Parser as JSON Schema Parser
participant Detector as Lookaround Detector
participant TypeSystem as Type Hint Resolver
participant Template as RootModel Template
participant Output as Generated Code
Parser->>Detector: provide fields and data-type constraints/patterns
Detector->>Detector: _has_lookaround_pattern() scans field patterns and nested DataType patterns
alt lookaround found
Detector->>Template: set use_base_type = True
Detector->>Template: request model_config regex_engine="python-re"
else no lookaround
Detector->>Template: set use_base_type = False
end
Template->>TypeSystem: request type hint for RootModel generic (use_base_type)
TypeSystem->>TypeSystem: compute base_type_hint or full type_hint (resolve constrained/containers/unions)
TypeSystem-->>Template: return chosen hint
Template->>Output: emit model with ConfigDict(regex_engine) and RootModel[<hint>]
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 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)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code graph analysis (1)tests/main/jsonschema/test_main_jsonschema.py (2)
⏰ 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)
🔇 Additional comments (1)
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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2721 +/- ##
==========================================
+ Coverage 99.34% 99.35% +0.01%
==========================================
Files 82 83 +1
Lines 11611 11838 +227
Branches 1405 1428 +23
==========================================
+ Hits 11535 11762 +227
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:
|
d6bd67b to
1b10ffe
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (1)
7-7: Unused import:Fieldis imported but not used.Line 7 imports
Fieldfrom pydantic, but it's not used in this generated file. Therootfield on line 14 uses the ellipsis (...) directly without wrapping inField(...).This is a minor issue in the generated code. Consider removing unused imports from the template or ensuring Field is used when needed.
src/datamodel_code_generator/types.py (1)
632-633: Remove unusednoqadirective.Static analysis indicates the
noqa: PLR0912, PLR0915directive on line 633 is unused. These complexity rules aren't triggered for this method.🔎 Proposed fix
@property - def base_type_hint(self) -> str: # noqa: PLR0912, PLR0915 + def base_type_hint(self) -> str: """Return the base type hint without constrained type kwargs.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
pyproject.toml(1 hunks)src/datamodel_code_generator/model/base.py(2 hunks)src/datamodel_code_generator/model/pydantic_v2/base_model.py(2 hunks)src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2(1 hunks)src/datamodel_code_generator/types.py(2 hunks)tests/cli_doc/test_cli_doc_coverage.py(5 hunks)tests/cli_doc/test_cli_options_sync.py(6 hunks)tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py(1 hunks)tests/data/jsonschema/lookaround_anyof_nullable.json(1 hunks)tests/data/jsonschema/lookaround_dict.json(1 hunks)tests/data/jsonschema/lookaround_dict_key.json(1 hunks)tests/data/jsonschema/lookaround_union_types.json(1 hunks)tests/data/jsonschema/nested_lookaround_array.json(1 hunks)tests/main/jsonschema/test_main_jsonschema.py(1 hunks)tests/model/test_base.py(1 hunks)tests/parser/test_base.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py (3)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py (2)
LookaroundStringArray(10-16)Model(19-20)
tests/main/jsonschema/test_main_jsonschema.py (2)
tests/test_main_kr.py (1)
output_file(44-46)tests/main/conftest.py (2)
output_file(94-96)run_main_and_assert(196-352)
src/datamodel_code_generator/model/base.py (2)
src/datamodel_code_generator/parser/base.py (1)
data_type(980-982)src/datamodel_code_generator/types.py (4)
is_union(619-621)base_type_hint(633-735)nullable(280-282)get_optional_type(247-255)
tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py (4)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py (2)
LookaroundStringArray(10-16)Model(19-20)tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py (2)
LookaroundStringArray(10-16)Model(19-20)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (2)
src/datamodel_code_generator/model/pydantic/base_model.py (2)
field(90-104)Constraints(36-48)src/datamodel_code_generator/types.py (1)
all_data_types(424-430)
tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/parser/test_base.py (1)
src/datamodel_code_generator/parser/base.py (1)
parse(2422-2711)
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (1)
tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (2)
LookaroundDict(10-14)Model(17-18)
src/datamodel_code_generator/types.py (2)
src/datamodel_code_generator/model/base.py (1)
base_type_hint(254-278)src/datamodel_code_generator/model/pydantic_v2/types.py (1)
_get_wrapped_reference_type_hint(46-50)
🪛 Ruff (0.14.8)
src/datamodel_code_generator/types.py
633-633: 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). (10)
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (32)
pyproject.toml (1)
189-194: LGTM: Appropriate test-specific lint suppressions.Centralizing PLR0904 (too many public methods) and PLR6301 (method doesn't use self) suppressions for test files is a good practice, as these are common and acceptable patterns in test code.
tests/cli_doc/test_cli_options_sync.py (1)
34-115: LGTM: Lint hygiene improvement.Removing inline
noqa: PLR6301comments is appropriate since this rule is now suppressed project-wide for test files via pyproject.toml. No functional changes.tests/cli_doc/test_cli_doc_coverage.py (1)
49-99: LGTM: Lint hygiene improvement.Removing inline
noqa: PLR6301comments aligns with the project-wide suppression in pyproject.toml. The minor signature reformatting has no functional impact.src/datamodel_code_generator/model/pydantic_v2/base_model.py (2)
231-232: LGTM: Clear delegation to extracted helper method.Extracting the lookaround detection logic into
_has_lookaround_pattern()improves code organization and readability.
262-273: LGTM: Well-structured lookaround pattern detection.The method correctly identifies lookaround patterns by:
- Detecting lookaround assertions:
(?=,(?!,(?<=,(?<!- Checking both field-level constraints and nested data types
- Returning early on first match for efficiency
The regex pattern
r"\(\?<?[=!]"appropriately matches all four lookaround types (positive/negative lookahead/lookbehind).tests/data/jsonschema/nested_lookaround_array.json (1)
1-18: LGTM: Valid test schema for lookaround patterns.The JSON Schema correctly defines a test case for lookaround patterns in nested array items. The pattern
^(?=.*[A-Z])(?=.*[0-9]).+$uses positive lookaheads to require both uppercase letters and digits, which is a valid use case for the Python regex engine.tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py (1)
10-20: LGTM: Expected output correctly demonstrates the fix.The generated code properly includes:
model_config = ConfigDict(regex_engine="python-re")on the RootModel- The lookaround pattern preserved in the
constrconstraint- Proper field description and type annotations
This validates that the PR's fix correctly applies
regex_engineconfiguration to RootModel generics containing lookaround patterns.tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py (1)
12-22: LGTM: Expected output for generic container variant.The generated code correctly handles the generic container case using
Sequence[str]while maintaining the same lookaround pattern handling withmodel_config = ConfigDict(regex_engine="python-re").tests/parser/test_base.py (1)
42-44: LGTM: Lint hygiene improvement.Removing inline
noqa: PLR6301comment aligns with the project-wide test file suppression in pyproject.toml.tests/data/jsonschema/lookaround_union_types.json (1)
1-21: LGTM! Well-structured test fixture for lookaround union types.The JSON schema correctly defines a union type with a lookaround pattern. The pattern
^(?=.*[A-Z]).+$appropriately tests positive lookahead (requiring at least one uppercase letter), which is the exact scenario requiringregex_engine="python-re"in Pydantic v2.tests/data/jsonschema/lookaround_dict_key.json (1)
1-19: LGTM! Correctly structured test fixture for lookaround patterns on dict keys.The schema appropriately uses
patternPropertiesto apply the lookaround pattern^(?=.*[A-Z]).+$to dictionary keys. This is a valuable test case since it validates lookaround support in key constraints (viapatternProperties), distinct from value constraints.Setting
additionalProperties: falseensures strict validation that only keys matching the pattern are allowed.tests/data/jsonschema/lookaround_dict.json (1)
1-17: LGTM! Well-structured test fixture for lookaround patterns on dict values.The schema correctly uses
additionalPropertieswith a pattern constraint to apply the lookaround pattern to dictionary values. This complementslookaround_dict_key.jsonby testing value constraints rather than key constraints, providing comprehensive coverage for dict-based lookaround scenarios.tests/data/jsonschema/lookaround_anyof_nullable.json (1)
1-21: LGTM! Good test coverage for nullable types with lookaround patterns.The schema correctly models a nullable string with a lookaround constraint using
anyOf, where the pattern applies only to the string alternative. This is an important edge case ensuring the fix handles nullable unions with lookaround patterns correctly.tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (1)
10-14: LGTM! Correct application of value constraints in dict RootModel.The generated code correctly:
- Uses base type
dict[str, str]in the RootModel generic parameter (line 10)- Applies the lookaround constraint via
constr(pattern=...)in the value position of the root field (line 14)- Configures
regex_engine="python-re"to support lookaround assertions (line 12)This demonstrates the PR's fix: separating the base type hint for generics from field-level constraints.
tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py (1)
10-16: The generic type parameterlist[str]is correct;Sequence[str]is not necessary.Pydantic v2 documentation uses
RootModel[list[str]]as the standard pattern, so the base type choice is intentional and appropriate. Additionally, theregex_engine="python-re"configuration is essential—Pydantic's default 'rust-regex' does not support lookaround assertions, while 'python-re' uses the re module which supports all regex features. The patternr'^(?=.*[A-Z])(?=.*[0-9]).+$'correctly enforces both uppercase and digit requirements via lookahead assertions with this engine setting. No changes needed.tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py (1)
12-16: LGTM!The generated code correctly demonstrates the fix for issue #2232. The
RootModelgeneric parameter uses the base typeMapping[str, str](avoiding class-definition-time evaluation of the constrained type), while therootfield declaration usesconstr(pattern=...)with the lookaround pattern. Theregex_engine="python-re"config ensures the Python regex engine handles the lookahead assertion.src/datamodel_code_generator/model/base.py (2)
223-230: LGTM!The
_build_base_union_type_hintmethod correctly mirrors_build_union_type_hintbut usesbase_type_hintfrom constituent data types. This enables proper Union type construction when forward references require base type hints.
253-278: LGTM!The
base_type_hintproperty correctly implements optional wrapping logic that parallels the existingtype_hintproperty. Theneeds_optionalandskip_optionalconditions properly handle nullability semantics for base type hints used in RootModel generics.src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 (1)
1-19: LGTM!The template update correctly implements the fix. When
config.regex_engineis set, the RootModel generic parameter usesbase_type_hint(avoiding class-definition-time evaluation of constrained types), while therootfield declaration continues to usetype_hintwith the full constraints. The comment on line 17 clearly documents the rationale.src/datamodel_code_generator/types.py (3)
424-430: LGTM!The
all_data_typesproperty now correctly yieldsdict_keytypes when present, ensuring complete traversal of nested DataTypes. This is important for detecting lookaround patterns in dictionary key types.
623-630: LGTM!The
_CONSTRAINED_TYPE_TO_BASEmapping correctly covers Pydantic's scalar constrained types. Container constrained types likeconlistaren't needed here since they don't affect the lookaround pattern issue.
644-735: LGTM!The
base_type_hintimplementation correctly handles all type variants: constrained types are mapped to their base types, composite types recursively usebase_type_hint, and container types properly propagate base type hints including fordict_key. The logic correctly mirrorstype_hintwhile providing the unconstrained type representation needed for RootModel generics.tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py (1)
10-16: LGTM!The generated code correctly handles the nullable union case. The
RootModel[str | None]generic uses base types while therootfield declaration includes theconstr(pattern=...)constraint with the lookahead assertion. Theregex_engine="python-re"config ensures proper pattern evaluation.tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (1)
10-16: LGTM!The generated code correctly handles the union case with mixed types. The
RootModel[str | int]generic uses base types, while therootfield declaration preservesconstr(pattern=...)for runtime validation. The pattern with lookahead assertion will be evaluated using Python's regex engine as configured.tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (1)
10-14: LGTM! Correct implementation of the RootModel generic fix for lookaround patterns.The
RootModel[dict[str, str]]correctly uses the base type in the generic parameter while therootfield uses the constrained typeconstr(pattern=...). Combined withregex_engine="python-re"in ConfigDict, this properly enables Python's regex engine for lookahead pattern support before Pydantic evaluates the pattern.tests/main/jsonschema/test_main_jsonschema.py (4)
4596-4618: LGTM! Test correctly validates allOf constraint merging for Pydantic v2.The test covers the core fix from issue #2232, ensuring that when merging pattern constraints with lookaround assertions, the generated RootModel uses the base type in the generic parameter.
4621-4640: LGTM! Good coverage for nested lookaround detection in array items.
4708-4722: Same verification needed for--use-generic-containerflag.This test also uses
--use-generic-container. See the comment above regarding verification of the flag name.
4725-4772: LGTM! Tests for standard collections and dict key lookaround patterns.These tests provide good coverage for the various type hint generation paths (standard collections, dict keys) when lookaround patterns are present.
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (3)
12-22: LGTM! Key demonstration of the RootModel generic fix.The contrast between
StringDatatype(line 12) andConstrainedStringDatatype(line 16) correctly shows the fix:
StringDatatype(RootModel[constr(pattern=...)])- pattern without lookaround, uses constrained type in genericConstrainedStringDatatype(RootModel[str])- pattern with lookahead(?=...), uses base type in generic withregex_engine="python-re"in ConfigDictThis ensures the regex_engine config is applied before Pydantic evaluates the lookaround pattern.
100-101: Verify pattern in dict key uses constrained type correctly.The
PatternPropsDatatypeuses the constrained typeconstr(pattern=r'^S_')in both the generic and root field. This pattern^S_doesn't contain lookaround, so this is the expected behavior.
141-161: LGTM! Model aggregator correctly references all generated types.The final
Modelclass properly aggregates all the optional fields referencing the various RootModel and BaseModel types defined above.
e41a508 to
167c75b
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py (1)
10-17: Generated output correctly handles lookaround patterns on dictionary keys.The structure follows the same pattern as the value-constrained dict: base types in the generic parameter, regex_engine config, then constrained root field. This ensures the lookaround pattern in the key constraint is properly evaluated with the Python regex engine.
Note: The past review comment about
constrdeprecation is valid for future consideration but is out of scope for this PR, which focuses on fixing the regex_engine config application.
🧹 Nitpick comments (1)
src/datamodel_code_generator/types.py (1)
632-735: Consider removing unusednoqadirectives and extracting shared logic.
The static analysis correctly flags that
# noqa: PLR0912, PLR0915on line 633 is unused - this method doesn't trigger those complexity warnings.There's significant code duplication between
base_type_hintandtype_hint. The core iteration logic for unions, tuples, lists, sets, and dicts is nearly identical. Consider extracting shared logic into a private helper method with a parameter to switch between returning constrained vs base types.🔎 Suggested fix for noqa directive
- @property - def base_type_hint(self) -> str: # noqa: PLR0912, PLR0915 + @property + def base_type_hint(self) -> str: """Return the base type hint without constrained type kwargs.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
pyproject.toml(1 hunks)src/datamodel_code_generator/model/base.py(2 hunks)src/datamodel_code_generator/model/pydantic_v2/base_model.py(2 hunks)src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2(1 hunks)src/datamodel_code_generator/types.py(2 hunks)tests/cli_doc/test_cli_doc_coverage.py(5 hunks)tests/cli_doc/test_cli_options_sync.py(6 hunks)tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py(1 hunks)tests/data/jsonschema/lookaround_anyof_nullable.json(1 hunks)tests/data/jsonschema/lookaround_dict.json(1 hunks)tests/data/jsonschema/lookaround_dict_key.json(1 hunks)tests/data/jsonschema/lookaround_union_types.json(1 hunks)tests/data/jsonschema/nested_lookaround_array.json(1 hunks)tests/main/jsonschema/test_main_jsonschema.py(1 hunks)tests/model/test_base.py(1 hunks)tests/parser/test_base.py(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- tests/parser/test_base.py
🚧 Files skipped from review as they are similar to previous changes (12)
- pyproject.toml
- tests/data/jsonschema/lookaround_dict.json
- tests/cli_doc/test_cli_options_sync.py
- tests/model/test_base.py
- tests/data/jsonschema/lookaround_dict_key.json
- tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py
- tests/cli_doc/test_cli_doc_coverage.py
- tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py
- src/datamodel_code_generator/model/pydantic_v2/base_model.py
- tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py
- src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2
- src/datamodel_code_generator/model/base.py
🧰 Additional context used
🧬 Code graph analysis (7)
tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (3)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (2)
LookaroundDict(10-14)Model(17-18)
tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py (2)
tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (2)
LookaroundDict(10-14)Model(17-18)tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (2)
LookaroundDict(10-14)Model(17-18)
tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (3)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py (2)
LookaroundDict(12-16)Model(19-20)
src/datamodel_code_generator/types.py (2)
src/datamodel_code_generator/model/base.py (2)
base_type_hint(254-278)nullable(711-713)src/datamodel_code_generator/model/pydantic_v2/types.py (1)
_get_wrapped_reference_type_hint(46-50)
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/main/jsonschema/test_main_jsonschema.py (2)
tests/test_main_kr.py (1)
output_file(44-46)tests/main/conftest.py (2)
output_file(94-96)run_main_and_assert(196-352)
🪛 Ruff (0.14.8)
src/datamodel_code_generator/types.py
633-633: 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). (15)
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.10 on Windows
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: benchmarks
🔇 Additional comments (16)
src/datamodel_code_generator/types.py (3)
423-430: LGTM! Correctly extends iteration to include dict_key.The modification ensures
dict_keytypes are recursively yielded, which is necessary for the lookaround pattern detection in_has_lookaround_pattern()to work correctly with dictionary key constraints.
623-630: LGTM! Well-structured constrained type mapping.The mapping covers the main constrained type functions (
constr,conint,confloat,condecimal,conbytes) to their base Python types. This is complete for the current Pydantic constrained types.
644-650: The# pragma: no coveron line 648-649 is justified and should not be removed. While RootModel fields with nullable lookaround patterns do occur in practice (as confirmed by test caselookaround_anyof_nullable_pydantic_v2.py), these are processed through the union branch ofbase_type_hint(lines 658-685), not the simpleif self.is_func and self.kwargs:branch. In the union path, optional constrained types are decomposed: theis_optionalflag is set on the parent union object, while individual constrained type components retainis_func=True, kwargs=True, is_optional=False. Consequently, the condition on line 648 (if self.is_optional and base_type != ANY) is never reached for constrained types, making the pragma coverage exclusion correct.tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (1)
10-14: Correctly demonstrates the fix for regex_engine with RootModel.The generated code properly separates concerns:
RootModel[dict[str, str]]uses base types in the generic parameter (avoiding premature regex evaluation)model_config = ConfigDict(regex_engine="python-re")is set before the field definitionroot: dict[str, constr(pattern=...)]applies the actual constraintThis ordering ensures Pydantic processes the regex_engine config before evaluating the lookaround pattern.
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (3)
12-22: Demonstrates selective application of regex_engine fix.The expected output correctly shows:
StringDatatype(line 12-13): No lookaround →RootModel[constr(...)]with constr in genericConstrainedStringDatatype(line 16-22): Has lookaround(?=...)→RootModel[str]with model_config and constr only in root fieldThis confirms the fix is correctly applied only when lookaround assertions are present, avoiding unnecessary changes to existing behavior.
100-101: Pattern with anchor^S_correctly kept in generic.The pattern
^S_doesn't contain lookaround assertions, soPatternPropsDatatypecorrectly usesRootModel[dict[constr(pattern=r'^S_'), str]]without the regex_engine config workaround.
141-161: Comprehensive test model aggregates all constraint scenarios.The
Modelclass provides good coverage for integration testing by composing all the constraint variants as optional fields.tests/data/jsonschema/lookaround_union_types.json (1)
1-21: Valid test schema for union type with lookaround pattern.The JSON Schema correctly defines a union (
anyOf) combining:
- A string with a lookaround pattern
^(?=.*[A-Z]).+$(requires at least one uppercase letter)- An integer
This is an effective test case for verifying that the regex_engine fix works correctly with union types, not just simple constrained strings.
tests/data/jsonschema/lookaround_anyof_nullable.json (1)
1-21: LGTM! Well-structured test fixture for lookaround with nullable.The JSON Schema correctly defines a nullable string with a lookaround pattern using
anyOf. The pattern^(?=.*[A-Z]).+$properly exercises positive lookahead assertions that require python-re engine support.tests/data/jsonschema/nested_lookaround_array.json (1)
1-18: LGTM! Test fixture correctly exercises nested lookaround in arrays.The schema properly defines array items with a lookaround pattern using two positive lookaheads
(?=.*[A-Z])(?=.*[0-9]), ensuring comprehensive testing of lookaround detection in nested data types.tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py (1)
12-16: LGTM! Correctly implements base type in RootModel generic.The generated code properly uses
RootModel[Mapping[str, str]]as the base type in the generic parameter, while therootfield contains the constrained type. This ensuresmodel_configwithregex_engine="python-re"is processed before pattern validation occurs.tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (1)
10-16: LGTM! Proper handling of lookaround in union types.The RootModel generic correctly uses the base union type
str | int, while the root field applies the pattern constraint. Theregex_engine="python-re"configuration is properly set.tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py (1)
10-16: LGTM! Nullable lookaround pattern correctly implemented.The code properly handles the nullable case with
RootModel[str | None]as the base type and applies the lookaround constraint in the root field definition.tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (1)
10-14: LGTM! Standard collections path correctly implemented.The generated code properly uses standard
dict[str, str]in the RootModel generic when--use-standard-collectionsis specified, while maintaining the pattern constraint in the root field.tests/main/jsonschema/test_main_jsonschema.py (2)
4596-4618: LGTM! Comprehensive test for allOf constraint merging with lookaround.The test properly validates the core PR objective: when merging pattern constraints with lookaround assertions, the RootModel generic uses base types to avoid premature regex evaluation. The docstring clearly explains the scenario and references the related issue.
4621-4772: LGTM! Comprehensive test coverage for lookaround scenarios.The test suite thoroughly covers lookaround pattern detection across multiple scenarios:
- Nested arrays with lookaround in item patterns
- Nullable types with anyOf unions
- Dict values with constrained strings
- Union types mixing constrained and plain types
- Container type variations (generic, standard collections)
- Dict keys with patterns
All tests properly use
--use-generic-container-types(the correct flag) and follow established patterns. The docstrings clearly explain each scenario being tested.
cab3215 to
3369c5e
Compare
3369c5e to
10a8796
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/datamodel_code_generator/types.py (2)
623-630: Clear documentation and appropriate mapping scope.The comments explain why only
constris included in the mapping—it's the only constrained type with apatternparameter that can trigger lookaround detection. This focused approach avoids unnecessary conversions for other constrained types.However, the unused
noqadirective at line 633 should be removed per the static analysis hint.🔎 Remove unused noqa directive
- def base_type_hint(self) -> str: # noqa: PLR0912, PLR0915 + def base_type_hint(self) -> str:
633-739: Consider refactoring to reduce duplication with type_hint.The
base_type_hintimplementation duplicates most of the logic fromtype_hint(lines 528-616), differing primarily in:
- Stripping constrained type kwargs for types in
_CONSTRAINED_TYPE_TO_BASE- Recursively calling
base_type_hintinstead oftype_hintfor nested typesWhile this works correctly, the ~110 lines of duplication increase maintenance burden. Consider extracting shared logic into a helper method that accepts a parameter to control whether to use base hints or full type hints.
💡 Example refactoring approach
def _build_type_hint(self, use_base: bool = False) -> str: """Build type hint with optional base type conversion.""" # Shared logic here, with conditional branches for use_base # Call recursively with same use_base parameter ... @property def type_hint(self) -> str: return self._build_type_hint(use_base=False) @property def base_type_hint(self) -> str: return self._build_type_hint(use_base=True)src/datamodel_code_generator/model/base.py (1)
223-231: base_type_hint implementation looks correct but duplicates type_hint/union logicThe new
_build_base_union_type_hintandbase_type_hintmirror the existing*_union_type_hintandtype_hintflows and appear logically consistent for unions, nullable, and default-factory cases. The main concern is maintainability: the optional/nullable decision tree and the union-forward-ref condition now live in two places, which makes future tweaks error‑prone.If this grows further, consider:
- Extracting a small shared helper for the optional-wrapping conditions used by both
type_hintandbase_type_hint.- Or parameterizing the union helper with a selector (
type_hintvsbase_type_hint) to avoid the near‑duplicate_build_*union_type_hintbodies.Given the current scope, this is non‑blocking but worth keeping in mind for future refactors.
Also applies to: 253-279
src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 (1)
1-10: RootModel generic switching to base_type_hint when regex_engine is set looks soundThe template correctly switches the RootModel generic from
type_hinttobase_type_hintwheneverconfig.regex_engineis truthy, which addresses the early‑evaluation problem for constrained patterns in issue #2232. One design question: this will also choose the base type for any future non‑default regex engine value, not just"python-re". That’s probably safe (generic argument becomes less specific, not more), but it’s worth confirming this matches your intended behavior for other possible engines as well.Also applies to: 17-20
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
pyproject.toml(1 hunks)src/datamodel_code_generator/model/base.py(2 hunks)src/datamodel_code_generator/model/pydantic_v2/base_model.py(2 hunks)src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2(1 hunks)src/datamodel_code_generator/types.py(2 hunks)tests/cli_doc/test_cli_doc_coverage.py(5 hunks)tests/cli_doc/test_cli_options_sync.py(6 hunks)tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_mixed_constraints_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py(1 hunks)tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py(1 hunks)tests/data/jsonschema/lookaround_anyof_nullable.json(1 hunks)tests/data/jsonschema/lookaround_dict.json(1 hunks)tests/data/jsonschema/lookaround_dict_key.json(1 hunks)tests/data/jsonschema/lookaround_mixed_constraints.json(1 hunks)tests/data/jsonschema/lookaround_union_types.json(1 hunks)tests/data/jsonschema/nested_lookaround_array.json(1 hunks)tests/main/jsonschema/test_main_jsonschema.py(1 hunks)tests/model/test_base.py(1 hunks)tests/parser/test_base.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- tests/data/jsonschema/lookaround_dict.json
- tests/data/jsonschema/nested_lookaround_array.json
- tests/cli_doc/test_cli_options_sync.py
- tests/data/jsonschema/lookaround_anyof_nullable.json
- tests/data/expected/main/jsonschema/nested_lookaround_array_standard_collections.py
- tests/data/jsonschema/lookaround_dict_key.json
- pyproject.toml
- tests/data/expected/main/jsonschema/lookaround_dict_generic_container.py
- tests/parser/test_base.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-18T13:43:06.494Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: tests/cli_doc/test_cli_doc_coverage.py:82-82
Timestamp: 2025-12-18T13:43:06.494Z
Learning: In datamodel-code-generator project, Ruff preview mode is enabled via `lint.preview = true` in pyproject.toml. This enables preview rules like PLR6301 (no-self-use), so `noqa: PLR6301` directives are necessary and should not be removed even if RUF100 suggests they are unused.
Applied to files:
tests/model/test_base.py
🧬 Code graph analysis (12)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (3)
src/datamodel_code_generator/model/base.py (2)
field(331-333)all_data_types(699-703)src/datamodel_code_generator/model/pydantic/base_model.py (2)
field(90-104)Constraints(36-48)src/datamodel_code_generator/types.py (1)
all_data_types(424-430)
tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
src/datamodel_code_generator/types.py (2)
src/datamodel_code_generator/model/base.py (2)
all_data_types(699-703)type_hint(233-251)src/datamodel_code_generator/model/pydantic_v2/types.py (1)
_get_wrapped_reference_type_hint(46-50)
tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_mixed_constraints_pydantic_v2.py (1)
src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/model/test_base.py (3)
src/datamodel_code_generator/model/base.py (2)
render(448-450)render(726-737)tests/parser/test_base.py (1)
render(295-297)src/datamodel_code_generator/model/typed_dict.py (1)
render(100-112)
tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (3)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (2)
LookaroundDict(10-14)Model(17-18)
src/datamodel_code_generator/model/base.py (3)
src/datamodel_code_generator/parser/base.py (1)
data_type(980-982)src/datamodel_code_generator/types.py (4)
is_union(619-621)base_type_hint(633-739)nullable(280-282)get_optional_type(247-255)src/datamodel_code_generator/parser/jsonschema.py (1)
type_has_null(418-427)
tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py (2)
src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
BaseModel(169-273)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(26-41)
🪛 Ruff (0.14.8)
src/datamodel_code_generator/types.py
633-633: 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). (11)
- GitHub Check: benchmarks
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
🔇 Additional comments (18)
tests/cli_doc/test_cli_doc_coverage.py (1)
49-49: LGTM: Formatting changes only.These method signature reformats (placing parameters on a single line) are purely cosmetic and have no functional impact. However, they appear unrelated to the PR's stated objective of fixing regex_engine config for RootModel generics.
Also applies to: 61-61, 71-71, 82-82, 93-93
tests/model/test_base.py (1)
34-34: No changes needed—inline noqa removal is appropriate.The project's pyproject.toml now includes PLR6301 in lint.per-file-ignores for tests/**/*.py, making the inline
noqa: PLR6301comment redundant. The removal aligns correctly with the updated project-wide lint configuration.src/datamodel_code_generator/model/pydantic_v2/base_model.py (2)
231-232: LGTM! Lookaround detection integrated correctly.The conditional check correctly invokes the new helper method to detect lookaround patterns and sets the
regex_engineconfiguration parameter accordingly. This ensures Pydantic v2 models can handle lookaround assertions in regex patterns.
262-273: LGTM! Lookaround pattern detection is comprehensive.The
_has_lookaround_patternmethod correctly:
- Uses regex pattern
r"\(\?<?[=!]"to detect all four lookaround assertions:(?=,(?!,(?<=,(?<!- Scans both field-level constraints and nested data type patterns via
all_data_types- Returns early on first match for efficiency
This addresses the core issue #2232 by enabling Python regex engine support when lookaround patterns are present.
src/datamodel_code_generator/types.py (1)
425-430: LGTM! Dictionary key support properly integrated.The docstring update and dict_key traversal correctly extend
all_data_typesto include dictionary key types, ensuring complete type graph traversal for lookaround pattern detection.tests/data/jsonschema/lookaround_mixed_constraints.json (1)
1-17: LGTM! Well-structured test case for mixed constraints.This JSON Schema correctly tests the scenario where a RootModel union contains both a constrained string with a lookaround pattern and a constrained integer. The pattern
^(?=.*[A-Z]).+$(requires at least one uppercase letter) is a valid positive lookahead that requires the Python regex engine.tests/data/jsonschema/lookaround_union_types.json (1)
1-21: LGTM! Comprehensive test for lookaround in referenced definitions.This schema tests lookaround pattern handling in a reusable type definition referenced via
$ref. TheanyOfunion between a string with lookaround pattern and an integer ensures the generator correctly detects lookaround patterns in referenced types.tests/data/expected/main/jsonschema/lookaround_dict_key_pydantic_v2.py (2)
10-17: LGTM! Correctly generates RootModel with lookaround-enabled dict key constraints.The generated model properly:
- Uses
RootModel[dict[str, str]]as the base generic type- Sets
regex_engine="python-re"inmodel_configto support the lookaround pattern- Constrains dictionary keys with
constr(pattern=r'^(?=.*[A-Z]).+$')- Includes descriptive Field metadata
This correctly implements the fix for issue #2232.
20-21: LGTM! Wrapper model correctly typed.The outer
Modelclass properly wraps theLookaroundKeyDictas an optional field, allowing for None values.tests/data/expected/main/jsonschema/lookaround_dict_pydantic_v2.py (1)
10-18: LGTM! Correctly generates RootModel with lookaround-enabled dict value constraints.The generated model properly handles lookaround patterns in dictionary values:
- Uses
RootModel[dict[str, str]]as the base- Sets
regex_engine="python-re"to support the lookaround pattern(?=.*[A-Z])- Constrains dictionary values (not keys) with
constr(pattern=...)This demonstrates the fix works for both dictionary keys and values.
tests/data/expected/main/jsonschema/lookaround_mixed_constraints_pydantic_v2.py (1)
10-20: LGTM! Key test case demonstrating base_type_hint for RootModel generics.This generated code correctly demonstrates the core fix:
- Generic parameter uses base types:
RootModel[str | conint(ge=0, le=100)](unconstrainedstr)- Root field uses constrained types:
constr(pattern=..., min_length=1) | conint(ge=0, le=100)model_configsetsregex_engine="python-re"to support the lookaround patternThis separation is necessary because the generic parameter is evaluated at class definition time before
model_configis processed, so it cannot useconstr(pattern=...)with lookaround patterns. Thebase_type_hintproperty introduced in types.py enables this correct code generation.tests/data/expected/main/jsonschema/lookaround_anyof_nullable_pydantic_v2.py (1)
10-20: LGTM! Correctly handles lookaround patterns with nullable types.The generated code properly demonstrates the fix working with nullable/optional types:
- Generic parameter:
RootModel[str | None]uses base typestr- Root field:
constr(pattern=...) | Noneuses constrained typeregex_engine="python-re"enables lookaround support for the nullable string patternThis ensures the fix handles optional/nullable constrained types correctly alongside the base_type_hint logic.
tests/data/expected/main/jsonschema/nested_lookaround_array_generic_container.py (1)
1-21: Fixture correctly exercises base_type_hint with generic container + lookaround
LookaroundStringArrayusesRootModel[Sequence[str]]for the generic and keeps the constrainedSequence[constr(...)]on therootfield withmodel_config = ConfigDict(regex_engine="python-re"), which is exactly what the new tests describe. No issues spotted in this expected output.tests/data/expected/main/jsonschema/lookaround_dict_standard_collections.py (1)
1-18: Expected dict/standard-collections fixture matches new RootModel behaviorThe generated
LookaroundDictusesRootModel[dict[str, str]]while therootvalue type isconstr(...), andmodel_configsetsregex_engine="python-re". This aligns with the intended base_type_hint behavior for standard collections; everything looks consistent.tests/data/expected/main/jsonschema/nested_lookaround_array_pydantic_v2.py (1)
1-20: Nested lookaround list fixture correctly uses base list type in RootModel generic
LookaroundStringArrayis parameterized asRootModel[list[str]]with constrainedlist[constr(...)]onrootandregex_engine="python-re"inmodel_config. This is the expected pattern for the non‑generic‑container list variant; no problems here.tests/data/expected/main/jsonschema/lookaround_union_types_pydantic_v2.py (1)
1-20: Union lookaround fixture demonstrates correct base_type_hint for unions
LookaroundUnionusesRootModel[str | int]as the generic while therootannotation isconstr(pattern=...) | intwithregex_engine="python-re". This cleanly exercises the union base_type_hint path and looks consistent with the intended behavior.tests/main/jsonschema/test_main_jsonschema.py (1)
4596-4788: New lookaround/regex_engine tests comprehensively cover the regression scenariosThe added benchmark tests around issue #2232 exercise all the critical paths: allOf + RootModel constraints, nested lookaround in arrays, nullable anyOf, mixed constr/conint unions, dict values and keys, plus both generic-container and standard-collections variants. The CLI flags and expected filenames look correct and consistent with existing patterns in this suite. I don’t see any issues here.
tests/data/expected/main/jsonschema/allof_root_model_constraints_merge_pydantic_v2.py (1)
1-161: Expected allOf/root-constraints fixture cleanly isolates the lookaround caseThis golden file correctly:
- Switches
ConstrainedStringDatatypetoRootModel[str]and addsmodel_config = ConfigDict(regex_engine="python-re")while keeping the constrainedconstr(...)onroot.- Leaves non‑lookaround RootModels (string patterns, numeric constraints, pattern props, etc.) using constrained generics without a regex_engine config.
- Aggregates everything in
Modelas optional references.That matches the intended fix and provides good coverage; no issues noted.
d8bb161 to
f1161b0
Compare
Fixes: #2232
Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.