Simplify generate() function signature using Unpack[GenerateConfigDict]#2874
Simplify generate() function signature using Unpack[GenerateConfigDict]#2874
Conversation
|
Warning Rate limit exceeded@koxudaxi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 18 minutes and 47 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR refactors the public generate() API to accept either a GenerateConfig object or keyword options, widens alias types to allow string-or-list values across config and parser types, expands public exports, and updates tests to reflect the new config-driven usage and mutual-exclusion error when both config and kwargs are provided. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant generate
participant GenerateConfig
participant Pydantic
participant ParserFactory
participant Codegen
Caller->>generate: call generate(input_, config=cfg) or generate(input_, **options)
alt config provided
generate->>GenerateConfig: use provided config
else kwargs provided
generate->>GenerateConfig: Construct from options (Unpack[GenerateConfigDict])
end
generate->>Pydantic: validate/rebuild config (v2 vs v1 guarded)
Pydantic-->>generate: resolved config
generate->>ParserFactory: instantiate parser(s) with config.parsers.* and aliases
ParserFactory->>Codegen: parse input and produce models
Codegen-->>generate: generated modules / string / None
generate-->>Caller: return result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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 |
CodSpeed Performance ReportMerging #2874 will not alter performanceComparing
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
tests/main/test_public_api_signature_baseline.py (1)
398-415: Config‑dict baseline check is solid; consider also assertinggenerate’s signature shapeComparing keyword‑only parameter names from
_baseline_generate(minus"config") toGenerateConfigDict.__annotations__.keys()is a good way to enforce parity between the legacy kwargs surface and the newGenerateConfigDictbacking type, and the mismatch message is clear.One thing you lose versus the previous version is any direct assertion about
generateitself (e.g. that it still has aconfigkw‑only parameter plus a**optionsvar‑kwarg usingGenerateConfigDict). To keep this test guarding the actual public function as well, you might additionally assert, for example:
inspect.signature(generate)has a kw‑onlyconfigparameter, and- its
VAR_KEYWORDparameter is named as expected (e.g.options).That would preserve the new dict‑based check while still catching future accidental signature changes.
src/datamodel_code_generator/__init__.py (2)
475-493: Consider removing unusednoqadirectives for local imports.Static analysis indicates the
# noqa: PLC0415comments on lines 475, 483-484, and 489-490 are unused. These are local imports inside the function, and the directive for local imports (PLC0415) may not be enabled in your linter configuration.If local imports are intentional (to avoid circular imports or for lazy loading), you can safely remove the
noqacomments since the rule isn't enabled.🔎 Proposed fix to remove unused noqa directives
- from datamodel_code_generator.config import GenerateConfig # noqa: PLC0415 + from datamodel_code_generator.config import GenerateConfig if config is None: if is_pydantic_v2(): - from datamodel_code_generator.model.pydantic_v2 import UnionMode # noqa: PLC0415 - from datamodel_code_generator.types import StrictTypes # noqa: PLC0415 + from datamodel_code_generator.model.pydantic_v2 import UnionMode + from datamodel_code_generator.types import StrictTypes GenerateConfig.model_rebuild(_types_namespace={"StrictTypes": StrictTypes, "UnionMode": UnionMode}) config = GenerateConfig.model_validate(options) else: - from datamodel_code_generator.enums import UnionMode # noqa: PLC0415 - from datamodel_code_generator.types import StrictTypes # noqa: PLC0415 + from datamodel_code_generator.enums import UnionMode + from datamodel_code_generator.types import StrictTypes GenerateConfig.update_forward_refs(StrictTypes=StrictTypes, UnionMode=UnionMode) config = GenerateConfig(**options)
495-616: Verbose but necessary for backward compatibility.The extraction of ~120 config values to local variables is verbose but maintains backward compatibility with the existing function body that references these variables. This avoids a larger refactor of the function internals.
For future consideration: the function body could be refactored to use
config.field_namedirectly, which would eliminate this extraction block. However, that's a larger change that can be deferred.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
docs/cli-reference/model-customization.mddocs/cli-reference/template-customization.mdsrc/datamodel_code_generator/__init__.pytests/main/test_main_general.pytests/main/test_public_api_signature_baseline.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfigDict(38-158)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__init__.py
450-450: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
475-475: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
483-483: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
484-484: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
489-489: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
490-490: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
🔇 Additional comments (9)
docs/cli-reference/model-customization.md (1)
1371-1379: Literal typing forApi.versionexample looks consistent and preciseImporting
Literaland tighteningApi.versiontoLiteral['v1']alongsideField('v1', const=True, ...)accurately reflects theconstconstraint and aligns this Pydantic v1 example with the other literal-based examples in the section.docs/cli-reference/template-customization.md (1)
76-77: Tightened MapState literals and added import are well-aligned with the schemaAdding
Literalto the typing imports and switchingmap_view_mode,map_split_mode, andis_splittoLiteral[...]types (while keeping the existingField(..., const=True, alias=...)) matches the JSON Schemaconstconstraints and makes the example’s static types more precise without changing the intended semantics.Also applies to: 2562-2564, 2574-2578
tests/main/test_public_api_signature_baseline.py (1)
605-612: PassingoutputviaGenerateConfigmakes the comparison test more representativeMoving
output=output_configinto theGenerateConfig(...)call and invokinggenerate(input_=schema, config=config)ensures this test now exercises the pure “config‑only” path versus the pure “kwargs‑only” path, without mixing shared options across both. That more accurately validates that config‑driven and kwargs‑driven generation remain behaviorally equivalent.tests/main/test_main_general.py (2)
1972-1995: LGTM!The test correctly validates that
GenerateConfignow accepts anoutputparameter and uses it properly. The test structure follows existing patterns.
1997-2014: LGTM!The new test properly validates the mutual exclusivity constraint between
configand keyword arguments. The test:
- Creates a config object without an output path
- Attempts to pass
outputas a keyword argument alongside the config- Correctly expects a
ValueErrorwith the appropriate messageThis ensures the API contract is enforced.
src/datamodel_code_generator/__init__.py (4)
477-479: LGTM!The mutual exclusivity check is correctly implemented. Raising
ValueErrorwhen bothconfigand**optionsare provided ensures a clear API contract and prevents ambiguous configurations.
635-640: LGTM!Using
DataclassArguments()to create an empty typed dict is correct. The subsequent conditional logic properly populatesfrozenandkw_onlykeys based on the config flags.
1080-1107: LGTM!The
__all__exports are appropriately expanded to include newly exposed public API elements likeDEFAULT_FORMATTERS,DEFAULT_SHARED_MODULE_NAME,AllOfMergeMode,CollapseRootModelsNameStrategy,FieldTypeCollisionStrategy,GraphQLScope,OpenAPIScope,PythonVersionMin, andReuseScope.
450-454: Thenoqadirectives on line 450 are technically unused and can be safely removed.The rules PLR0912, PLR0914, and PLR0915 are explicitly listed in
lint.ignorein pyproject.toml, so Ruff will not check these violations regardless of thenoqadirectives. Since the rules are disabled at the configuration level, the directives have no effect. They can be removed without consequence, though keeping them for documentation purposes is also acceptable given the function's 603-line span.
1457063 to
356d859
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/__init__.py (1)
450-450: Remove unusednoqadirectives.Static analysis reports that several
noqadirectives are unused:
- Line 450:
PLR0912,PLR0914,PLR0915(complexity warnings)- Lines 475, 483-484, 489-490:
PLC0415(import-outside-top-level)However, the runtime imports in lines 475, 483-484, 489-490 appear to still be present. Please verify whether these
noqadirectives are actually needed, and if not, remove them to keep the code clean.🔎 Proposed fix
-def generate( # noqa: PLR0912, PLR0914, PLR0915 +def generate( input_: Path | str | ParseResult | Mapping[str, Any], *, config: GenerateConfig | None = None, **options: Unpack[GenerateConfigDict], ) -> str | GeneratedModules | None: """Generate Python data models from schema definitions or structured data. This is the main entry point for code generation. Supports OpenAPI, JSON Schema, GraphQL, and raw data formats (JSON, YAML, Dict, CSV) as input. Args: input_: The input source (file path, string content, URL, or dict). config: A GenerateConfig object with all options. Cannot be used together with **options. **options: Individual options matching GenerateConfig fields. Cannot be used together with config. Returns: - When output is a Path: None (writes to file system) - When output is None and single module: str (generated code) - When output is None and multiple modules: GeneratedModules (dict mapping module path tuples to generated code strings) Raises: ValueError: If both config and **options are provided. """ - from datamodel_code_generator.config import GenerateConfig # noqa: PLC0415 + from datamodel_code_generator.config import GenerateConfig if config is not None and options: msg = "Cannot specify both 'config' and keyword arguments. Use one or the other." raise ValueError(msg) if config is None: if is_pydantic_v2(): - from datamodel_code_generator.model.pydantic_v2 import UnionMode # noqa: PLC0415 - from datamodel_code_generator.types import StrictTypes # noqa: PLC0415 + from datamodel_code_generator.model.pydantic_v2 import UnionMode + from datamodel_code_generator.types import StrictTypes GenerateConfig.model_rebuild(_types_namespace={"StrictTypes": StrictTypes, "UnionMode": UnionMode}) config = GenerateConfig.model_validate(options) else: - from datamodel_code_generator.enums import UnionMode # noqa: PLC0415 - from datamodel_code_generator.types import StrictTypes # noqa: PLC0415 + from datamodel_code_generator.enums import UnionMode + from datamodel_code_generator.types import StrictTypes GenerateConfig.update_forward_refs(StrictTypes=StrictTypes, UnionMode=UnionMode) config = GenerateConfig(**options)Note: Only remove the
noqacomments if linting confirms they're genuinely unused. The complexity warnings may be valid to suppress.Also applies to: 475-475, 483-484, 489-490
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/config.pytests/main/test_main_general.pytests/main/test_public_api_signature_baseline.py
🧰 Additional context used
🧬 Code graph analysis (3)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfigDict(38-158)
src/datamodel_code_generator/__init__.py (7)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfigDict(38-158)src/datamodel_code_generator/config.py (1)
GenerateConfig(59-191)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/enums.py (3)
UnionMode(192-196)StrictTypes(213-220)DataclassArguments(15-27)src/datamodel_code_generator/types.py (1)
model_rebuild(414-421)src/datamodel_code_generator/parser/jsonschema.py (1)
model_rebuild(228-230)src/datamodel_code_generator/model/base.py (4)
model_rebuild(200-207)base_class(837-839)class_name(848-850)class_name(853-857)
tests/main/test_main_general.py (4)
tests/test_main_kr.py (1)
output_file(44-46)tests/main/conftest.py (1)
output_file(98-100)src/datamodel_code_generator/config.py (1)
GenerateConfig(59-191)src/datamodel_code_generator/__init__.py (1)
generate(450-1051)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__init__.py
450-450: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
475-475: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
483-483: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
484-484: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
489-489: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
490-490: Unused noqa directive (non-enabled: PLC0415)
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). (20)
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on macOS
- GitHub Check: 3.12 on macOS
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: py312-black24 on Ubuntu
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.13 on Ubuntu
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (13)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
49-49: LGTM! Type expansion for aliases field.The change from
Mapping[str, str]toMapping[str, str | list[str]]allows each alias to map to either a single string or a list of strings, providing greater flexibility. This is consistent with parallel changes inGenerateConfigDictand the config models.src/datamodel_code_generator/_types/generate_config_dict.py (1)
55-55: LGTM! Consistent type expansion.The aliases field type expansion matches the change in
ParserConfigDict, maintaining consistency across the configuration type definitions.src/datamodel_code_generator/config.py (2)
88-88: LGTM! Consistent type expansion in GenerateConfig.The aliases field type matches the corresponding TypedDict definition, maintaining type consistency across the configuration models.
223-223: LGTM! Consistent type expansion in ParserConfig.The change aligns with the GenerateConfig model and the TypedDict definitions, ensuring uniform alias handling across parsers.
tests/main/test_public_api_signature_baseline.py (2)
452-469: LGTM! Test correctly validates new config-driven signature.The test now verifies that
GenerateConfigDictkeys match the baseline function's keyword-only arguments (excluding 'config'), which appropriately validates backward compatibility for the new**options: Unpack[GenerateConfigDict]signature.
659-666: LGTM! Test correctly demonstrates config-driven usage.The test now passes
outputvia theGenerateConfigobject rather than as a keyword argument togenerate(), correctly demonstrating the new config-driven API pattern while ensuring functional parity with the kwargs path.tests/main/test_main_general.py (2)
979-995: LGTM! Test updated for config-driven usage.The test now correctly passes
outputthrough theGenerateConfigobject, demonstrating the intended config-driven pattern for the new API.
998-1014: LGTM! Test correctly validates mutual exclusivity.The test appropriately verifies that passing both a
configobject and keyword arguments raises aValueErrorwith the expected message, ensuring proper enforcement of the mutual exclusivity constraint.src/datamodel_code_generator/__init__.py (5)
12-13: LGTM! Import changes support config-driven API.The new imports (
defaultdict,Mapping,Unpack,GenerateConfigDict) are all necessary for the refactored signature and config handling logic.Also applies to: 28-28, 63-63
450-494: LGTM! Clean migration to config-driven API.The signature refactoring successfully:
- Simplifies the API by accepting either a
GenerateConfigobject or individual options via**options: Unpack[GenerateConfigDict]- Enforces mutual exclusivity between
configand**optionswith a clear error message- Properly handles Pydantic v1 vs v2 differences (model_validate vs init, model_rebuild vs update_forward_refs)
The approach maintains backward compatibility through the
**optionspath while enabling the cleaner config object pattern.
495-616: LGTM! Systematic config extraction maintains compatibility.The extraction of all config values to local variables ensures the rest of the function continues to work unchanged. The special handling for
extra_template_data(converting todefaultdictwhen provided) is appropriate given the function's internal expectations.
636-636: LGTM! Proper initialization of DataclassArguments.The explicit initialization of
DataclassArguments()ensures the variable is properly typed and prevents potential issues when conditionally adding keys.
1080-1111: LGTM! Expanded public exports for convenience.The additions to
__all__expose commonly used constants and enums (DEFAULT_FORMATTERS,DEFAULT_SHARED_MODULE_NAME,AllOfMergeMode,CollapseRootModelsNameStrategy,FieldTypeCollisionStrategy,GraphQLScope,OpenAPIScope,PythonVersionMin,ReuseScope), improving the public API surface without breaking changes.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2874 +/- ##
=======================================
Coverage 99.39% 99.39%
=======================================
Files 91 91
Lines 15591 15618 +27
Branches 1831 1836 +5
=======================================
+ Hits 15496 15523 +27
Misses 50 50
Partials 45 45
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:
|
356d859 to
8cfddbb
Compare
8cfddbb to
8134931
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/main/test_public_api_signature_baseline.py (1)
349-408: Union-string normalization helper looks solid; consider guarding for older Python
_normalize_union_strplus its parametrized tests correctly canonicalize unions (including nested generics likeMapping[str, str | list[str]] | None]) so that config vs TypedDict types compare reliably.One nuance: this relies on
ast.unparse, which is only available on Python ≥3.9. The test module already depends ontypes.UnionType(Python ≥3.10), but if you ever need the test suite to run on <3.9, this will fail at import time.If cross-version testing matters, a cheap defensive guard would be:
Optional compatibility guard for <3.9
def _normalize_union_str(type_str: str) -> str: - """Normalize a union type string by sorting its components recursively.""" - try: - tree = ast.parse(type_str, mode="eval") - except SyntaxError: # pragma: no cover - return type_str + """Normalize a union type string by sorting its components recursively.""" + # ast.unparse is only available in Python 3.9+; on older versions just + # return the original string so tests still run. + if not hasattr(ast, "unparse"): # pragma: no cover + return type_str + try: + tree = ast.parse(type_str, mode="eval") + except SyntaxError: # pragma: no cover + return type_strCan you confirm your CI and supported test Python versions so this remains safe?
src/datamodel_code_generator/__init__.py (1)
496-618: Consider refactoring the config extraction block.This ~120-line block that extracts every field from
configinto local variables is quite verbose and creates a maintenance burden. Each change toGenerateConfigrequires updating this extraction logic.Since you're using "Chill" review mode, this is an optional suggestion for future refactoring rather than a blocking issue. The current approach works and might be intentional to keep the PR scope limited to signature changes.
💡 Potential refactoring approach
Consider these alternatives for future iterations:
- Pass config directly to parser: Update the parser constructor to accept
config: GenerateConfigand extract fields internally- Use config attributes directly: Reference
config.field_namethroughout the function instead of extracting to locals- Dataclass unpacking: Use
**config.model_dump()or similar if the parser constructor signature can be updatedThese would reduce the code size and make maintenance easier, but would require more extensive refactoring.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/config.pysrc/datamodel_code_generator/parser/base.pysrc/datamodel_code_generator/parser/graphql.pysrc/datamodel_code_generator/parser/jsonschema.pysrc/datamodel_code_generator/parser/openapi.pysrc/datamodel_code_generator/reference.pytests/main/test_public_api_signature_baseline.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/datamodel_code_generator/config.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/datamodel_code_generator/__init__.py (5)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfigDict(39-160)src/datamodel_code_generator/config.py (1)
GenerateConfig(60-193)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/enums.py (3)
UnionMode(199-203)StrictTypes(220-227)DataclassArguments(15-27)src/datamodel_code_generator/types.py (1)
model_rebuild(414-421)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfigDict(39-160)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/__init__.py
451-451: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
476-476: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
484-484: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
485-485: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
490-490: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
491-491: Unused noqa directive (non-enabled: PLC0415)
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). (13)
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: 3.11 on macOS
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (14)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
56-56: LGTM! Consistent with ParserConfigDict changes.The aliases type widening matches the corresponding change in
ParserConfigDict, maintaining consistency across configuration types. This enables Pydantic v2 AliasChoices support at the generation level.src/datamodel_code_generator/parser/jsonschema.py (1)
661-661: LGTM! Implementation already supports list aliases.The parameter type widening aligns with the TypedDict changes and is well-supported by the existing implementation. Multiple locations in the codebase (lines 1227-1233, 2367-2372, 2548-2565) already handle both string and list aliases correctly using
isinstancechecks:if isinstance(alias, list): validation_aliases = alias else: single_alias = aliasThis backward-compatible change enables Pydantic v2 AliasChoices functionality.
src/datamodel_code_generator/_types/parser_config_dict.py (1)
50-50: Type widening for multi-alias support aligns with Pydantic v2 integration.The change from
Mapping[str, str]toMapping[str, str | list[str]]correctly widens the type to support multiple aliases per field, consistent with Pydantic v2's AliasChoices feature. This is a backward-compatible change since existingMapping[str, str]values remain valid. The type definition itself is sound and properly reflects the intended schema.src/datamodel_code_generator/parser/base.py (1)
690-711: Alias type widening inParser.__init__is consistentChanging
aliasestoMapping[str, str | list[str]] | NonematchesModelResolver/FieldNameResolverexpectations and cleanly enables multi-alias (AliasChoices) without affecting existing string-only callers.src/datamodel_code_generator/reference.py (1)
523-575: ModelResolver aliases type aligned with FieldNameResolverThe
aliases: Mapping[str, str | list[str]] | Noneparameter is correctly propagated intoFieldNameResolver, keeping alias semantics consistent while allowing multiple aliases per field.src/datamodel_code_generator/parser/graphql.py (1)
103-136: GraphQLParser aliases signature matches core parser API
aliases: Mapping[str, str | list[str]] | Noneis correctly widened and forwarded toParser.__init__, keeping the GraphQL parser in sync with the new multi-alias support.src/datamodel_code_generator/parser/openapi.py (1)
185-216: OpenAPIParser aliases parameter updated appropriatelyThe
aliaseskwarg type is widened toMapping[str, str | list[str]] | Noneand passed through to the base parser, matching the rest of the alias-handling stack.tests/main/test_public_api_signature_baseline.py (3)
55-75: Baseline aliases parameters updated to multi-alias typeThe
_baseline_generateand_BaselineParser.__init__signatures now usealiases: Mapping[str, str | list[str]] | None, matching the real API andGenerateConfigDict/ParserConfigDicttypes so the baseline tests accurately track the public surface.Also applies to: 184-205
455-472: Signature baseline now directly validated againstGenerateConfigDict
test_generate_signature_matches_baselinecomparing baseline kw-only args (excludingconfig) toGenerateConfigDict.__annotations__is a nice tightening: it ensures the Unpack-basedgenerate()signature stays aligned with the TypedDict keys and gives a clear diff when something drifts.
634-674: Config vs kwargs output equivalence test is precise and robust
test_generate_with_config_produces_same_result_as_kwargsnow writes to two explicit files (output_kwargs.pyandoutput_config.py) and compares their contents, withGenerateConfig(output=output_config, ...)mirroring the kwargs path. This is a good, minimal check that the newconfig-driven path is behaviorally identical to the kwargs path.src/datamodel_code_generator/__init__.py (4)
1083-1115: LGTM! Public API expansion is correctly implemented.The newly exported constants and types are all properly imported from their respective modules and align with the PR objective to expand the public API surface. This makes these types more accessible for users who want to configure generation programmatically.
482-494: Performance: Forward reference resolution executes on every call; remove unusednoqadirectives.Two concerns:
Performance issue: Lines 487 and 493 call
model_rebuild(Pydantic v2) orupdate_forward_refs(Pydantic v1) every timegenerate()is invoked without aconfigparameter. These operations should be performed once at module initialization time, not on every function call, to avoid unnecessary overhead.Unused
noqadirectives: Lines 484, 485, 490, 491 have unusednoqa: PLC0415directives that should be removed per static analysis.💡 Suggested approach for forward reference resolution
Consider moving the forward reference resolution to module initialization:
# Near the top of the module, after imports if is_pydantic_v2(): from datamodel_code_generator.model.pydantic_v2 import UnionMode from datamodel_code_generator.types import StrictTypes from datamodel_code_generator.config import GenerateConfig GenerateConfig.model_rebuild(_types_namespace={"StrictTypes": StrictTypes, "UnionMode": UnionMode}) else: from datamodel_code_generator.enums import UnionMode from datamodel_code_generator.types import StrictTypes from datamodel_code_generator.config import GenerateConfig GenerateConfig.update_forward_refs(StrictTypes=StrictTypes, UnionMode=UnionMode)Then in the
generate()function, simply construct the config without rebuilding:if config is None: if is_pydantic_v2(): config = GenerateConfig.model_validate(options) else: config = GenerateConfig(**options)⛔ Skipped due to learnings
Learnt from: koxudaxi Repo: koxudaxi/datamodel-code-generator PR: 2799 File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43 Timestamp: 2025-12-25T09:22:22.481Z Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.Learnt from: koxudaxi Repo: koxudaxi/datamodel-code-generator PR: 2799 File: src/datamodel_code_generator/util.py:49-66 Timestamp: 2025-12-25T09:23:08.506Z Learning: In datamodel-code-generator, the is_pydantic_v2() and is_pydantic_v2_11() functions in src/datamodel_code_generator/util.py intentionally use global variable caching (_is_v2, _is_v2_11) on top of lru_cache for performance optimization. This dual-layer caching eliminates function call overhead and cache lookup overhead for frequently-called version checks. The PLW0603 linter warnings should be suppressed with # noqa: PLW0603 as this is a deliberate design choice.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:16.235Z 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.
476-481: Remove unusednoqadirective, but the mutual exclusion logic is correct.Line 476 has an unused
noqa: PLC0415directive that should be removed. However, the mutual exclusion check itself is correctly implemented and provides a clear error message.🔎 Proposed fix
- from datamodel_code_generator.config import GenerateConfig # noqa: PLC0415 + from datamodel_code_generator.config import GenerateConfig⛔ Skipped due to learnings
Learnt from: koxudaxi Repo: koxudaxi/datamodel-code-generator PR: 2799 File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43 Timestamp: 2025-12-25T09:22:22.481Z Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.
451-451: Remove unusednoqadirective.The complexity warnings (
PLR0912,PLR0914,PLR0915) are not being triggered, so thenoqadirective can be removed.🔎 Proposed fix
-def generate( # noqa: PLR0912, PLR0914, PLR0915 +def generate( input_: Path | str | ParseResult | Mapping[str, Any],⛔ Skipped due to learnings
Learnt from: koxudaxi Repo: koxudaxi/datamodel-code-generator PR: 2799 File: src/datamodel_code_generator/model/pydantic/__init__.py:43-43 Timestamp: 2025-12-25T09:22:22.481Z Learning: In datamodel-code-generator project, defensive `# noqa: PLC0415` directives should be kept on lazy imports (imports inside functions/methods) even when Ruff reports them as unused via RUF100, to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.
Breaking Change AnalysisResult: Breaking changes detected Reasoning: The PR removes the ability to pass both a Content for Release NotesAPI/CLI Changes
This analysis was performed by Claude Code Action |
|
🎉 Released in 0.51.0 This PR is now available in the latest release. See the release notes for details. |
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.