Refactor config handling and add CLI TypedDicts#2830
Conversation
📝 WalkthroughWalkthroughRefactors the project to a config-driven architecture: adds Pydantic config models (GenerateConfig, ParserConfig, ParseConfig, CliConfigSchema), generates TypedDicts, and updates generate(), CLI, and Parser constructors to accept/validate config objects or config dicts. Tests and tooling updated to support generation and validation of config types. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant generate as generate()
participant GenCfg as GenerateConfig
participant Parser as Parser
participant ParseCfg as ParserConfig / ParseSettings
rect `#dfeef7`
Note over User,GenCfg: Config-driven invocation
User->>+generate: generate(input, config=cfg OR **options)
generate->>GenCfg: validate/construct GenerateConfig (model_validate/model_dump)
activate GenCfg
GenCfg-->>generate: validated GenerateConfig
deactivate GenCfg
generate->>Parser: Parser(source, config=ParserConfig._from_generate_config(cfg))
Parser->>ParseCfg: build ParserConfig / ParseSettings
activate ParseCfg
ParseCfg-->>Parser: ParseSettings
deactivate ParseCfg
Parser->>Parser: parse(config=ParseSettings)
Parser-->>generate: Result (modules/output)
generate-->>-User: write output (config.output / encoding)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used🧬 Code graph analysis (1)tests/main/test_main_general.py (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). (11)
🔇 Additional comments (11)
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 |
|
📚 Docs Preview: https://pr-2830.datamodel-code-generator.pages.dev |
CodSpeed Performance ReportMerging #2830 will not alter performanceComparing
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (10)
src/datamodel_code_generator/parser/graphql.py (2)
92-115: Config-driven__init__wiring looks solidThe mutual exclusivity check,
model_validate(ParserConfig, ...)usage, and delegation tosuper().__init__(source=source, config=config)all look consistent with the new config pattern and should keep GraphQLParser aligned with the base parser behavior. The post-init assignment ofself.use_standard_collectionsfromconfigis redundant because Parser already sets it, but it's harmless; you could drop it later for clarity if desired.
102-110: Ruff: unused# noqa: PLC0415on local ParserConfig importRuff reports this
# noqa: PLC0415as unused (rule not enabled). You can either remove the directive here or enablePLC0415in your Ruff config if you intend to keep suppressing it.src/datamodel_code_generator/parser/openapi.py (1)
181-189: Ruff: unused# noqa: PLC0415on local ParserConfig importRuff flags the
# noqa: PLC0415here as unused. Consider removing it (or enablingPLC0415in Ruff) to keep linter suppressions meaningful.src/datamodel_code_generator/__init__.py (2)
885-899: *Consider exporting the ConfigDict types in__all__for a fully public surface
__getattr__exposesGenerateConfigDict,ParserConfigDict, andParseConfigDict, but they aren’t listed in__all__. If you intend these TypedDicts to be part of the public API (as implied by the new design), adding them to__all__would make their exposure consistent with the config models and help users relying onfrom datamodel_code_generator import *.Possible `__all__` extension
__all__ = [ @@ - "GenerateConfig", + "GenerateConfig", + "GenerateConfigDict", @@ - "ParseConfig", - "ParserConfig", + "ParseConfig", + "ParseConfigDict", + "ParserConfig", + "ParserConfigDict",
74-75: Ruff: several unused# noqasuppressionsRuff reports some of these
# noqacomments (e.g.,# noqa: E402on theis_pydantic_v2import and# noqaon the generate definition) as unused because those codes aren’t enabled. You can trim them back to only the active rules to keep the file’s linter state tidy.src/datamodel_code_generator/__main__.py (2)
1099-1133: Silent failure on malformed extra_template_data / aliases / custom_formatters_kwargsThe additional type checks for
extra_template_data,aliases, andcustom_formatters_kwargsare good, but on failure they currently justreturn Exit.ERRORwithout any diagnostic output. That can make it hard for users to understand what went wrong when a pyproject or CLI value is mis-typed.Consider emitting a brief error message to stderr indicating which option was invalid before returning
Exit.ERROR.
42-43: Ruff: unused# noqasuppressionsRuff reports some of the
# noqacomments here (e.g.,# noqa: TC003on theMapping, Sequenceimport and# noqa: N805on validators) as unused for your current configuration. Trimming these back to only the active rules will keep the file a bit cleaner.src/datamodel_code_generator/parser/base.py (2)
2792-2836: _prepare_parse_config() and ParseSettings cleanly separate parse-time concerns
_prepare_parse_config()now returns aParseSettingsNamedTuple that bundleswith_import,use_deferred_annotations,code_formatter,module_split_mode, and all-exports settings. That keeps parse-time behavior (imports, formatting, exports) independent of the full ParseConfig model while preserving the existing logic for deferred annotations andfrom __future__imports.If you ever need to surface more parse-time knobs, extending ParseSettings instead of threading additional parameters will keep this pattern scalable.
699-707: Ruff: unused# noqasuppressions around imports and signaturesRuff indicates some of the
# noqadirectives here (e.g., on the localParserConfigimport and theparse/__init__complexity codes) are unused with your current linter configuration. Cleaning these up (or enabling the corresponding rules) would make it easier to spot meaningful suppressions.src/datamodel_code_generator/_types/cli_config_dict.py (1)
83-83: Consider making ParseResult more specific.The
ParseResulttype is defined astuple[Any, Any, Any, Any, Any, Any], which provides no type safety. If this represents a URL parse result (as suggested by the name and its usage in line 159 for theurlfield), consider usingurllib.parse.ParseResultdirectly or at minimum documenting what each position represents.Example improvement
If this represents
urllib.parse.ParseResult, you could use:from urllib.parse import ParseResult as UrlParseResult ParseResult: TypeAlias = UrlParseResultOr if maintaining compatibility with the tuple form is required, at least document it:
# ParseResult mirrors urllib.parse.ParseResult: (scheme, netloc, path, params, query, fragment) ParseResult: TypeAlias = tuple[Any, Any, Any, Any, Any, Any]
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
pyproject.tomlsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/_types/__init__.pysrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_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.pytests/main/test_main_general.pytox.ini
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/__init__.py
🧬 Code graph analysis (6)
src/datamodel_code_generator/config.py (4)
src/datamodel_code_generator/_types/generate_config_dict.py (2)
DataclassArguments(35-45)GenerateConfig(104-226)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(29-55)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(22-29)
src/datamodel_code_generator/parser/openapi.py (3)
src/datamodel_code_generator/util.py (3)
model_copy(275-279)model_dump(254-258)model_validate(261-265)src/datamodel_code_generator/parser/base.py (1)
parse(3105-3199)src/datamodel_code_generator/config.py (2)
ParserConfig(593-713)ParserConfigDict(197-309)
src/datamodel_code_generator/_types/generate_config_dict.py (2)
src/datamodel_code_generator/enums.py (15)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)GraphQLScope(155-158)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)StrictTypes(199-206)UnionMode(192-196)src/datamodel_code_generator/config.py (1)
GenerateConfig(324-454)
src/datamodel_code_generator/_types/parse_config_dict.py (2)
src/datamodel_code_generator/enums.py (3)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)ModuleSplitMode(172-178)src/datamodel_code_generator/config.py (1)
ParseConfig(716-733)
src/datamodel_code_generator/parser/jsonschema.py (4)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(67-179)src/datamodel_code_generator/config.py (2)
ParserConfig(593-713)ParserConfigDict(197-309)src/datamodel_code_generator/util.py (2)
model_validate(261-265)model_copy(275-279)src/datamodel_code_generator/format.py (1)
DatetimeClassType(50-57)
src/datamodel_code_generator/_types/cli_config_dict.py (2)
src/datamodel_code_generator/enums.py (15)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)StrictTypes(199-206)TargetPydanticVersion(181-189)UnionMode(192-196)src/datamodel_code_generator/config.py (1)
CliConfigSchema(457-590)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/config.py
[error] 51-51: Ruff: Do not catch blind exception: Exception (BLE001) in fallback for minimal installs
[error] 331-333: D106 Missing docstring in public nested class
[error] 464-466: D106 Missing docstring in public nested class
[error] 600-602: D106 Missing docstring in public nested class
[error] 723-725: D106 Missing docstring in public nested class
[error] 1-1: Pre-commit hooks ruff-format and ruff failed during 'prek run --all-files'.
src/datamodel_code_generator/_types/cli_config_dict.py
[warning] 1-1: ruff-format reformatted 4 files as part of pre-commit hooks; please review and commit changes.
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
51-51: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
52-52: Do not catch blind exception: Exception
(BLE001)
src/datamodel_code_generator/__init__.py
74-74: Unused noqa directive (non-enabled: E402)
Remove unused noqa directive
(RUF100)
466-466: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
483-483: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
500-500: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
606-606: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
895-895: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/openapi.py
181-181: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__main__.py
42-42: Unused noqa directive (non-enabled: TC003)
Remove unused noqa directive
(RUF100)
175-175: Unused noqa directive (non-enabled: N805)
Remove unused noqa directive
(RUF100)
500-500: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
501-501: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
503-503: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
504-504: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
505-505: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
587-587: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
1011-1011: Unused noqa directive (non-enabled: T201)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/graphql.py
102-102: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/base.py
691-691: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
699-699: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3105-3105: Unused noqa directive (non-enabled: PLR0914)
Remove unused noqa directive
(RUF100)
3112-3112: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/jsonschema.py
534-534: 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). (12)
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (19)
tox.ini (1)
17-20: Config-types tox env wired correctly to new profiles
config-typesis added toenv_listand the dedicated[testenv:config-types]runs the four profile-based generation commands withdependency_groups = devandno_default_groups = true, which is appropriate and isolated from test deps.Also applies to: 81-89
tests/main/test_main_general.py (2)
5-7: Extra-template-data and file-based config validation tests look solidThe new tests around
Config(extra_template_data=...)and themain()-level rejection of invalidextra_template_data,aliases, andcustom_formatters_kwargsfiles exercise important edge cases (None/dict/file-like inputs, bad key/value types) without overreaching. The monkeypatch ofConfig.parse_objintest_main_rejects_invalid_extra_template_datais scoped and restores behavior via the original implementation.Also applies to: 108-132, 134-173
27-32: Config vs. individual options contract for generate()/Parser/parse() is well-coveredThe tests for:
generate()raising onconfig+ extra options and accepting a config mapping,Parser.__init__(viaDummyParser,GraphQLParser,JsonSchemaParser,OpenAPIParser) rejecting mixed config/options but accepting dict configs, andParser.parse()rejecting mixed config/options while accepting dict configs,give good coverage of the new config-driven API and its error messages. The use of both model instances (
GenerateConfig,ParserConfig,ParseConfig) and plain dicts matches the intended flexibility.Also applies to: 200-265, 267-325
src/datamodel_code_generator/_types/parser_config_dict.py (1)
11-65: Generated ParserConfig TypedDict matches config model surfaceThe Literal aliases and
ParserConfigTypedDict fields line up with the correspondingParserConfig/ParserConfigDictmodel inconfig.py(same option names, compatible container types likedict/list). This should be a safe, strongly-typed surface for consumers of the generated config types.Also applies to: 67-179
src/datamodel_code_generator/_types/parse_config_dict.py (1)
11-20: ParseConfig TypedDict correctly reflects ParseConfig modelThe Literal aliases and
ParseConfigTypedDict fields (includingsettings_pathasstr | Noneand the all-exports/module-split options) are consistent withParseConfiginconfig.pyand the corresponding enums, so downstream use of these generated types should be safe.Also applies to: 22-29
src/datamodel_code_generator/parser/jsonschema.py (1)
78-84: Config-driven JsonSchemaParser.init is consistent with new APIThe new signature and body:
- Cleanly separate
config: ParserConfig | Nonefrom**options: Unpack[ParserConfigDict].- Enforce the “no mixing config with individual options” contract tested in
test_main_general.py.- Accept both dict and
ParserConfiginstances viamodel_validate, and normalize a defaulttarget_datetime_classusingmodel_copywhen unset.- Delegate to
Parser.__init__with the resolved config, keeping the rest of the parser logic unchanged.This aligns well with the broader config refactor and the new tests around parser initialization.
Also applies to: 523-547
pyproject.toml (1)
261-279: Profiles correctly wire config models to generated TypedDict modulesThe four
[tool.datamodel-codegen.profiles.*]sections point at the newGenerateConfig,ParserConfig,ParseConfig, andCliConfigSchemamodels and generate their TypedDict representations into the expected_types/*.pypaths. This matches the new toxconfig-typesenv and keeps the TypedDicts reproducible from the single source-of-truth config models.src/datamodel_code_generator/config.py (2)
72-195: Config models and TypedDicts provide a coherent, central config surfaceThe new
GenerateConfigDict/GenerateConfig,ParserConfigDict/ParserConfig, andParseConfigDict/ParseConfigpairs:
- Mirror the existing CLI/generate options (names and defaults) closely, so behavior should remain backward compatible.
- Use
Mapping/Sequence/Pathin the runtime-facing dicts and models, while the generated_typesmodules expose simplerdict/list/str-based TypedDicts for external consumers.- Are wired to Pydantic v1/v2 via
is_pydantic_v2()andConfigDict, withextra="forbid"andarbitrary_types_allowed=True, which is appropriate for these rich config objects.The shapes look internally consistent and align with the new tests and profiles; once the small lint issues above are fixed, this should be a solid foundation for the refactored config handling.
Also applies to: 197-322, 324-455, 457-591, 593-714, 716-733
47-53: Keep the defensive noqa: PLC0415 on lazy importsThe runtime import fallback for
UnionModeshould keep the# noqa: PLC0415directive even though it appears unused. This project maintains defensive noqa directives on all lazy imports (imports inside functions/methods) to prepare for potential future Ruff configuration changes that might enable the import-outside-toplevel rule.Narrowing the exception from
ExceptiontoImportErroris a reasonable improvement:else: try: from datamodel_code_generator.model.pydantic_v2 import UnionMode # noqa: PLC0415 except ImportError: # pragma: no cover - fallback for minimal installs UnionMode = Any # type: ignore[assignment]This satisfies BLE001 while preserving the defensive noqa for future compatibility.
Likely an incorrect or invalid review comment.
src/datamodel_code_generator/parser/openapi.py (1)
170-193: OpenAPIParser config normalization and datetime default look correctThe new
config/optionshandling mirrors the base Parser pattern, and themodel_validate(ParserConfig, ...)calls should keep external usages backward compatible. Thetarget_datetime_classfallback toDatetimeClassType.Awaredatetimepreserves an OpenAPI-specific default while still allowing explicit overrides via ParserConfig/GenerateConfig.If you haven't already, it’s worth double-checking older tests that relied on implicit aware datetime handling for OpenAPI to ensure they still pass with this new config-based path.
src/datamodel_code_generator/__init__.py (2)
451-492: generate(...): config-driven entrypoint is well wired; verify parse defaultsThe new
generate()overloads and body correctly:
- enforce
configvsoptionsexclusivity,- normalize any dict-like configs via
model_validate(GenerateConfig, ...), and- bridge into ParserConfig/ParseConfig using
model_dump+ field filtering.This should preserve external behavior while centralizing all parser settings under
GenerateConfig. One thing to sanity-check via tests is that the implicit defaults forwith_importandformat_(now coming fromParseConfigdefaults) still match the previous behavior ofgenerate()when output isNonevs aPath.
678-707: ParserConfig bridging viamodel_dump/model_validatelooks robustBuilding
parser_config_data = model_dump(config)and then:
- injecting parser-only fields (
data_model_type,data_model_root_type,data_type_manager_type,dump_resolve_reference_action,base_path,remote_text_cache,default_field_extras, datetime/date targets, etc.), and- filtering keys against
ParserConfig.model_fields/__fields__beforemodel_validate(ParserConfig, ...)gives a clean separation between GenerateConfig and ParserConfig while avoiding stray keys. This should make it straightforward to extend either config model independently.
src/datamodel_code_generator/__main__.py (3)
143-188: Config subclassing GenerateConfig is a good consolidationMaking
Configinherit fromGenerateConfigand adding CLI-specific validators (for paths, URLs, headers, JSON files) keeps a single source of truth for configuration while still handling CLI concerns. The conditional pydantic v2 helpers (parse_obj,get_fields,model_config) look correct and should preserve v1/v2 behavior.
587-627: to_generate_config(): adapter from CLI Config to GenerateConfig looks correct
to_generate_config()cleanly:
- starts from
model_dump(self),- strips CLI-only keys (
input,check,watch, etc.),- maps legacy flags
use_default/force_optionalontoapply_default_values_for_required_fieldsandforce_optional_for_required_fields, and- injects runtime-only values (
extra_template_data,aliases,custom_formatters_kwargs,output,command_line,settings_path)before validating to
GenerateConfig. This should keep existing CLI semantics while aligning with the new generate(config=...) API.If you have coverage for combinations of
use_default/force_optionaland the newer flags from both CLI and pyproject, it’s worth ensuring they still behave as expected with this adapter in place.
925-945: run_generate_from_config(): streamlined hand-off togenerateThe new
run_generate_from_config()correctly builds aGenerateConfigviaConfig.to_generate_config(...)and always callsgenerate(input_=input_, config=generate_config), which simplifies the flow and centralizes config validation in one place. The explicit casting ofextra_template_datatodict[str, dict[str, Any]] | Nonematches whatto_generate_config()expects.src/datamodel_code_generator/parser/base.py (2)
691-823: Parser.init: centralized ParserConfig handling looks consistentThe new
__init__signature and body:
- enforce mutual exclusivity between
configand**options,- normalize any dict-like configs via
model_validate(ParserConfig, ...), and- map ParserConfig fields into instance attributes and the
DataTypeManagerconstruction,which aligns well with the rest of the refactor. The normalization of
extra_template_datato adefaultdict(dict, ...)also preserves the previous mutation-friendly behavior for template metadata.
3105-3185: parse(...): config-based entrypoint matches other config patternsThe new
parse(*, config: ParseConfigModel | None = None, **options)method:
- mirrors the same config-vs-options exclusivity and
model_validate(ParseConfigModel, ...)pattern used ingenerate()and parser constructors,- pulls the needed fields (
with_import,format_,settings_path,disable_future_imports,all_exports_scope,all_exports_collision_strategy,module_split_mode) out of the config, and- feeds them into
_prepare_parse_config()and_build_module_structure().This should remain backward compatible for callers that previously passed
with_import,format_, etc., directly, while offering a structured ParseConfig-based API.It’s worth confirming via tests that existing code which calls
parse(with_import=False, format_=False, ...)still behaves as expected when those arguments are now routed through ParseConfig defaults and ParseSettings.src/datamodel_code_generator/_types/generate_config_dict.py (1)
159-163: No action needed. Type difference is by design and handled correctly by Pydantic.GenerateConfigDict uses
list[str]to represent the JSON/dict input format (JSON arrays), while GenerateConfig usesset[str]for internal efficiency. Pydantic v2 automatically coerces lists to sets during model validation viamodel_validate(), so no explicit validator is required. This pattern is intentional and correct—aligning the types would actually break the JSON serialization design.src/datamodel_code_generator/_types/cli_config_dict.py (1)
163-167: The type definitions are intentional and correctly designed. The TypedDict incli_config_dict.pyuseslist[str]because it represents JSON-serializable configuration data, while the Pydantic model inconfig.pyusesset[str]for internal use with automatic list-to-set coercion during model validation. This is a proper design pattern, not a type mismatch requiring alignment.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/datamodel_code_generator/_types/cli_config_dict.py (1)
1-3: Formatting issue already flagged in previous review.Run
ruff formaton this file to pass CI.src/datamodel_code_generator/_types/generate_config_dict.py (1)
1-3: Formatting issue already addressed in previous review.Run
ruff formaton all files insrc/datamodel_code_generator/_types/to resolve the pipeline failure.
🧹 Nitpick comments (1)
src/datamodel_code_generator/_types/cli_config_dict.py (1)
83-83: ParseResult type alias may not match stdlib's ParseResult.The generated
ParseResult: TypeAlias = tuple[Any, Any, Any, Any, Any, Any]is a 6-tuple approximation ofurllib.parse.ParseResult. While this works for JSON/CLI serialization, consumers expecting the actualParseResultnamed tuple (with.scheme,.netloc, etc. attributes) may be surprised.Consider adding a comment clarifying this is a serialization-compatible representation, not the actual
urllib.parse.ParseResult.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/config.pytests/main/test_main_general.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/datamodel_code_generator/_types/parse_config_dict.py
- tests/main/test_main_general.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/config.py (5)
src/datamodel_code_generator/_types/generate_config_dict.py (2)
DataclassArguments(35-45)GenerateConfig(104-226)src/datamodel_code_generator/_types/parser_config_dict.py (1)
DataclassArguments(17-27)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(29-55)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/__main__.py (1)
Config(143-627)
src/datamodel_code_generator/_types/cli_config_dict.py (3)
src/datamodel_code_generator/enums.py (15)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)StrictTypes(199-206)TargetPydanticVersion(181-189)UnionMode(192-196)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/config.py (1)
CliConfigSchema(467-602)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/_types/parser_config_dict.py
[error] 1-1: ruff-format reformatted 4 files. Commit the changes or re-run the pipeline.
src/datamodel_code_generator/_types/generate_config_dict.py
[error] 1-1: ruff-format reformatted 4 files. Commit the changes or re-run the pipeline.
src/datamodel_code_generator/_types/cli_config_dict.py
[error] 1-1: ruff-format reformatted 4 files. Commit the changes or re-run the pipeline.
⏰ 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: 3.13 on Ubuntu
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (10)
src/datamodel_code_generator/config.py (7)
80-203: Well-structured TypedDict for generate configuration.
GenerateConfigDictcomprehensively covers all generation options with appropriate optional typing viatotal=False. The field types align with the correspondingGenerateConfigBaseModel.
205-318: ParserConfigDict is comprehensive and well-typed.The TypedDict covers parser initialization options thoroughly. Types are consistent with
ParserConfigBaseModel fields.
320-330: ParseConfigDict is concise and correctly defined.Covers the parse-time options appropriately with optional fields.
332-465: GenerateConfig BaseModel is well-implemented with proper v1/v2 compatibility.The Pydantic v1/v2 handling pattern using
is_pydantic_v2()is correct. The nestedConfigclass now includes a docstring (addressing D106). Default values are sensible and consistent with the TypedDict counterpart.
467-603: CliConfigSchema properly extends configuration for CLI usage.Includes CLI-specific fields (
input,check,debug,watch, etc.) alongside shared configuration. The v1/v2 compatibility pattern is consistent.
605-728: ParserConfig provides comprehensive parser initialization options.Includes type-based fields (
data_model_type,data_type_manager_type, etc.) with proper defaults pointing to pydantic model types. The structure is sound.
730-749: ParseConfig is minimal and correctly scoped.Contains only parse-time options with sensible defaults. The structure is clean.
src/datamodel_code_generator/_types/parser_config_dict.py (1)
67-179: ParserConfig TypedDict is comprehensive and correctly typed.All fields use
NotRequiredappropriately for optional configuration. The type aliases reference the Literal definitions at the top of the file consistently.src/datamodel_code_generator/_types/cli_config_dict.py (1)
104-229: CliConfigSchema TypedDict is correctly structured.All CLI configuration options are present with appropriate
NotRequiredwrappers. Field types use the Literal-based type aliases defined above, ensuring type safety.src/datamodel_code_generator/_types/generate_config_dict.py (1)
104-226: GenerateConfig TypedDict is comprehensive and correctly structured.All generation options are represented with proper
NotRequiredtyping. The intentional type conversions (e.g.,Path→str,set→list) for JSON/CLI serialization compatibility are appropriate for this generated typing surface.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2830 +/- ##
==========================================
- Coverage 99.52% 99.48% -0.04%
==========================================
Files 90 92 +2
Lines 13999 14710 +711
Branches 1668 1719 +51
==========================================
+ Hits 13932 14634 +702
- Misses 36 39 +3
- Partials 31 37 +6
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:
|
|
|
||
| from datamodel_code_generator.model.base import DataModel, DataModelFieldBase | ||
| from datamodel_code_generator.model.pydantic_v2 import UnionMode | ||
| from datamodel_code_generator.types import DataTypeManager, StrictTypes |
Check notice
Code scanning / CodeQL
Cyclic import Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
General approach: Break the cycle by removing or deferring the problematic import while preserving runtime behavior. Since the imported names are only used for type annotations and are not required at runtime, the lowest-risk fix is to avoid importing datamodel_code_generator.types at all in this module and instead annotate those attributes using Any (or a forward reference if we had access to the definitions). This follows the existing pattern in the file where other potentially cyclic types fall back to Any in the non-TYPE_CHECKING branch.
Concrete fix for this file:
- In the
TYPE_CHECKINGblock (lines 40–47), remove the linefrom datamodel_code_generator.types import DataTypeManager, StrictTypes. - In the corresponding
elseblock (lines 48–56),DataTypeManagerandStrictTypesare already defined asAny, so no change is required there. - Update type annotations that reference
StrictTypesto avoid needing the real type. In this snippet,strict_types: Sequence[StrictTypes] | None = None(line 149) is the only such usage. To eliminate the need for the actualStrictTypestype while maintaining a useful annotation, change this to useAnyin the sequence, e.g.Sequence[Any] | None, which is acceptable sinceAnyis already imported at the top of the file.
This change removes the import that forms the cycle, keeps runtime behavior identical, and only slightly weakens type information for one field, which is acceptable in the context of a config model.
| @@ -44,7 +44,6 @@ | ||
| from datamodel_code_generator.model import DataModelSet | ||
| from datamodel_code_generator.model.base import DataModel, DataModelFieldBase | ||
| from datamodel_code_generator.model.pydantic_v2 import UnionMode | ||
| from datamodel_code_generator.types import DataTypeManager, StrictTypes | ||
| else: | ||
| if not is_pydantic_v2(): | ||
| Path = Any # type: ignore[assignment] | ||
| @@ -146,7 +145,7 @@ | ||
| use_generic_container_types: bool = False | ||
| enable_faux_immutability: bool = False | ||
| disable_appending_item_suffix: bool = False | ||
| strict_types: Sequence[StrictTypes] | None = None | ||
| strict_types: Sequence[Any] | None = None | ||
| empty_enum_field_name: str | None = None | ||
| custom_class_name_generator: CallableSchema | None = None | ||
| field_extra_keys: set[str] | None = None |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/datamodel_code_generator/parser/base.py (1)
71-87: Parser config/parse refactor is coherent and matches the new config models
Parser.__init__’sconfig/optionsnormalization viamodel_validate(ParserConfig, …)and the mutual-exclusion guard align with howGenerateConfig/ParseConfigare handled elsewhere.- Introducing
ParseSettingsas a lightweight internal carrier for parse-time options simplifies_process_single_module,_generate_module_output, and_generate_empty_init_exportswithout changing behavior._prepare_parse_config()still correctly drivesuse_deferred_annotations, future imports, and optionalCodeFormatter.- The new imports of
DataType/DataTypeManagerand their usage in helpers keep types explicit and consistent with the newParserConfigfields.I’m deliberately ignoring Ruff’s RUF100 suggestions about
# noqa: PLC0415on the lazy imports, since those directives are intentionally kept for future Ruff configuration changes. Based on learnings, this is expected.Also applies to: 128-138, 691-825, 2794-2838, 3000-3070, 3072-3195
src/datamodel_code_generator/_types/cli_config_dict.py (1)
1-214: CLI config TypedDict surface matches the Pydantic schema and enum valuesThe Literal aliases and
CliConfigSchemafields line up with the documented enum values andCliConfigSchemamodel (paths as strings, set-like options as lists, etc.), giving a useful typed surface for CLI configs. The looserunion_mode: Anyis acceptable here and avoids pulling in pydantic-specific types into this generated stub; you can tighten it later if you decide to mirror those literals more precisely.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
pyproject.tomlsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_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.pytests/main/test_main_general.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/datamodel_code_generator/_types/parser_config_dict.py
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.pypyproject.tomlsrc/datamodel_code_generator/parser/base.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/__init__.py
📚 Learning: 2025-12-18T13:35:21.591Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: .coderabbit.yaml:4-6
Timestamp: 2025-12-18T13:35:21.591Z
Learning: CodeRabbit's Ruff tool configuration supports the `config_file` property in `.coderabbit.yaml` to specify the path to the Ruff configuration file (e.g., "pyproject.toml", "ruff.toml", or ".ruff.toml"), as documented at https://docs.coderabbit.ai/tools#configuration-methods.
Applied to files:
pyproject.toml
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
pyproject.tomlsrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
🧬 Code graph analysis (10)
src/datamodel_code_generator/parser/graphql.py (2)
src/datamodel_code_generator/util.py (1)
model_validate(261-265)src/datamodel_code_generator/config.py (3)
ParserConfig(601-723)ParserConfigDict(201-313)_rebuild_config_models(751-786)
src/datamodel_code_generator/_types/parse_config_dict.py (3)
src/datamodel_code_generator/model/typed_dict.py (1)
TypedDict(49-114)src/datamodel_code_generator/enums.py (3)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)ModuleSplitMode(172-178)src/datamodel_code_generator/config.py (1)
ParseConfig(726-745)
src/datamodel_code_generator/config.py (3)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfig(91-211)src/datamodel_code_generator/parser/__init__.py (2)
DefaultPutDict(28-47)LiteralType(20-25)src/datamodel_code_generator/__main__.py (1)
Config(143-627)
src/datamodel_code_generator/parser/jsonschema.py (4)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(63-173)src/datamodel_code_generator/config.py (3)
ParserConfig(601-723)ParserConfigDict(201-313)_rebuild_config_models(751-786)src/datamodel_code_generator/util.py (2)
model_validate(261-265)model_copy(275-279)src/datamodel_code_generator/format.py (1)
DatetimeClassType(50-57)
tests/main/test_main_general.py (6)
src/datamodel_code_generator/config.py (7)
GenerateConfig(328-460)ParseConfig(726-745)ParserConfig(601-723)Config(335-339)Config(470-474)Config(608-612)Config(733-737)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(20-27)src/datamodel_code_generator/parser/graphql.py (1)
GraphQLParser(65-507)src/datamodel_code_generator/parser/jsonschema.py (2)
JsonSchemaParser(520-3291)Config(368-373)src/datamodel_code_generator/__main__.py (1)
Config(143-627)src/datamodel_code_generator/parser/openapi.py (1)
OpenAPIParser(165-748)
src/datamodel_code_generator/__init__.py (2)
src/datamodel_code_generator/util.py (3)
is_pydantic_v2(52-57)model_dump(254-258)model_validate(261-265)src/datamodel_code_generator/http.py (1)
get_body(29-45)
src/datamodel_code_generator/_types/generate_config_dict.py (5)
src/datamodel_code_generator/enums.py (5)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)InputFileType(35-45)src/datamodel_code_generator/_types/cli_config_dict.py (1)
DataclassArguments(33-43)src/datamodel_code_generator/_types/parser_config_dict.py (1)
DataclassArguments(17-27)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/config.py (1)
GenerateConfig(328-460)
src/datamodel_code_generator/parser/openapi.py (4)
src/datamodel_code_generator/parser/base.py (1)
parse(3107-3208)src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(63-173)src/datamodel_code_generator/config.py (3)
ParserConfig(601-723)ParserConfigDict(201-313)_rebuild_config_models(751-786)src/datamodel_code_generator/model/base.py (1)
DataModelFieldBase(151-468)
src/datamodel_code_generator/_types/cli_config_dict.py (2)
src/datamodel_code_generator/enums.py (14)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)StrictTypes(199-206)TargetPydanticVersion(181-189)src/datamodel_code_generator/config.py (1)
CliConfigSchema(463-598)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/config.py (6)
GenerateConfig(328-460)Config(335-339)Config(470-474)Config(608-612)Config(733-737)_rebuild_config_models(751-786)src/datamodel_code_generator/util.py (2)
model_dump(254-258)model_validate(261-265)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/parser/graphql.py
102-102: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/config.py
754-754: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
755-755: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
757-757: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
758-758: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
761-761: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/jsonschema.py
534-534: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/base.py
691-691: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
699-699: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3107-3107: Unused noqa directive (non-enabled: PLR0914)
Remove unused noqa directive
(RUF100)
3114-3114: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3117-3117: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__init__.py
74-74: Unused noqa directive (non-enabled: E402)
Remove unused noqa directive
(RUF100)
466-466: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
483-483: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
507-507: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
613-613: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
902-902: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/openapi.py
181-181: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__main__.py
42-42: Unused noqa directive (non-enabled: TC003)
Remove unused noqa directive
(RUF100)
175-175: Unused noqa directive (non-enabled: N805)
Remove unused noqa directive
(RUF100)
500-500: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
501-501: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
503-503: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
504-504: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
505-505: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
587-587: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
727-727: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
729-729: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
748-748: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
750-750: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
751-751: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1022-1022: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1029-1029: Unused noqa directive (non-enabled: T201)
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). (12)
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.11 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (11)
tests/main/test_main_general.py (3)
5-6: New imports for config and parser types look consistentBringing in
GenerateConfig,ParseConfig,ParserConfig, and the concrete parser classes keeps tests strongly typed against the new config-driven API; no issues here.Also applies to: 27-32
108-173: Config and CLI validation tests are well targetedThe new tests around
Config.extra_template_data, invalidextra_template_dataviaparse_obj, and malformed aliases/custom formatter kwargs exercise exactly the new validation paths without overreaching; they should catch most regressions in CLI/config coercion logic.
200-325: Good coverage of config vs options contract across generate/Parser/parseThese tests clearly enforce “
configXOR individual options” forgenerate(),Parser.__init__,JsonSchemaParser.parse(), and the GraphQL/OpenAPI/JSONSchema parser constructors, while also confirming that plain mapping configs are accepted and wired through. This gives strong safety net for the new config-driven API.src/datamodel_code_generator/config.py (2)
76-326: TypedDict and BaseModel config surfaces are coherent and strongly typed
GenerateConfigDict,ParserConfigDict,ParseConfigDictand their correspondingGenerateConfig/ParserConfig/ParseConfigmodels line up well: field names, enum types, and option shapes are consistent with the rest of the project. Usingextra="forbid"on the models is a good choice to catch mis-spelled or unsupported options early.
328-786: Lazy forward-ref rebuild pattern is appropriate; keep PLC0415noqamarkers
_rebuild_config_models()centralizes the heavy imports (Path,ParseResult,DataModel,DataTypeManager,UnionMode) and applies them viamodel_rebuild/update_forward_refs, which avoids hard import cycles while still giving fully-typed models at runtime. The local imports in this helper, and in callers that re-import config inside methods, justify the# noqa: PLC0415directives even if RUF100 flags them as unused; they’re a deliberate guard against future linter configuration changes. Based on learnings, this pattern is intentional and should remain.src/datamodel_code_generator/_types/parse_config_dict.py (1)
11-27: Generated ParseConfig TypedDict matches runtime modelThe TypedDict aliases and
ParseConfigkeys mirror theParseConfigBaseModel fields (including enum literals for scope/collision strategy/split mode), which is exactly what downstream tooling and type-checkers need.pyproject.toml (1)
261-283: Profiles for generating TypedDict config surfaces are well wiredThe four
[tool.datamodel-codegen.profiles.*]entries correctly reference the new config models and their corresponding_types/*.pyoutputs, using consistent Ruff-based formatting. This should keep the TypedDict interfaces in sync with the runtime config models with minimal maintenance.src/datamodel_code_generator/parser/jsonschema.py (1)
79-84: Config-driven JsonSchemaParser.init is sound and cycle-safeNormalizing configuration via
config: ParserConfig | Noneplus**options: Unpack[ParserConfigDict], rejecting mixed usage, and then defaultingtarget_datetime_classbefore callingsuper().__init__gives a clear, strongly-typed surface. The lazy import ofParserConfigand_rebuild_config_models()inside__init__(with# noqa: PLC0415) is appropriate to avoid import cycles while still resolving forward refs at first use. This matches the new tests and overall config design.Also applies to: 526-549
src/datamodel_code_generator/parser/graphql.py (1)
32-34: GraphQL parser config plumbing anduse_standard_collectionswiring look solidThe new
config/optionshandling,_rebuild_config_models()call, andmodel_validate(ParserConfig, …)usage are consistent with the baseParserrefactor. Derivingself.use_standard_collectionsfromconfig.use_standard_collectionsand threading it into_typename_fieldandparse_fieldpreserves prior behavior while aligning with the centralized config model.Also applies to: 42-48, 92-118, 192-205, 347-363
src/datamodel_code_generator/__init__.py (1)
60-83: Config-drivengenerate()pipeline is well-wired and backwards compatibleThe new overloads plus the
GenerateConfig/GenerateConfigDict+model_validatenormalization provide a clean, typed entry point while still supporting legacy keyword options. Input routing,remote_text_cacheusage, parser selection, parser/parse-config construction, and defer-formatting behavior all look consistent with previous semantics and the new centralized config models.Also applies to: 451-515, 519-575, 576-715, 722-781, 783-861
src/datamodel_code_generator/parser/openapi.py (1)
27-28: OpenAPI parser’s config-based constructor and datetime defaulting look correctThe new
config/optionshandling forOpenAPIParser.__init__is consistent with the sharedParserConfigpattern, including_rebuild_config_models()andmodel_validate(ParserConfig, …). Defaultingtarget_datetime_classtoDatetimeClassType.Awaredatetimewhen unset keeps the OpenAPI-specific behavior explicit while leaving the generic config model neutral.Also applies to: 39-40, 170-195
| extra_template_data: dict[str, dict[str, Any]] | None | ||
| if config.extra_template_data is None: | ||
| extra_template_data = None | ||
| else: | ||
| with config.extra_template_data as data: | ||
| try: | ||
| extra_template_data = json.load(data, object_hook=lambda d: defaultdict(dict, **d)) | ||
| except json.JSONDecodeError as e: | ||
| print(f"Unable to load extra template data: {e}", file=sys.stderr) # noqa: T201 | ||
| return Exit.ERROR | ||
| try: | ||
| extra_template_data = defaultdict(dict, **config.extra_template_data) | ||
| except (TypeError, ValueError): | ||
| return Exit.ERROR |
There was a problem hiding this comment.
Add error messages for validation failures.
When extra_template_data construction fails, the code returns Exit.ERROR without printing an error message. Users will see an exit code of 2 without understanding what went wrong.
🔎 Proposed fix to add error message
- try:
- extra_template_data = defaultdict(dict, **config.extra_template_data)
- except (TypeError, ValueError):
- return Exit.ERROR
+ try:
+ extra_template_data = defaultdict(dict, **config.extra_template_data)
+ except (TypeError, ValueError) as e:
+ print(f"Error: Invalid extra_template_data format: {e}", file=sys.stderr) # noqa: T201
+ return Exit.ERROR🤖 Prompt for AI Agents
In src/datamodel_code_generator/__main__.py around lines 1117-1124 the code
swallows TypeError/ValueError when building extra_template_data and simply
returns Exit.ERROR; update the except block to print or log a clear error
message to stderr (or the module logger) that includes a short description (e.g.
"Invalid extra_template_data"), the exception message, and the offending
config.extra_template_data value for debugging, and then return Exit.ERROR as
before.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/datamodel_code_generator/_types/cli_config_dict.py (2)
14-153: Duplicate Enum definitions (same as generate_config_dict.py).These Enum classes are identical to those in
generate_config_dict.py. Refer to the comment on that file regarding extracting these to a shared module.
255-255: Loose typing forunion_modefield (same issue as generate_config_dict.py).Same type safety concern as in
generate_config_dict.pyline 254. The verification script from that file will also reveal the correct type for this field.
🧹 Nitpick comments (2)
src/datamodel_code_generator/_types/parse_config_dict.py (1)
14-26: Consider consolidating duplicated Enum definitions.These three Enums (
AllExportsCollisionStrategy,AllExportsScope,ModuleSplitMode) are identically defined across multiple_typesmodules (cli_config_dict.py, generate_config_dict.py, parse_config_dict.py). While this duplication may be intentional in the generation process to avoid cross-dependencies, it creates maintenance overhead and risk of inconsistency.If the generation architecture allows, consider extracting these shared Enums to a common
_types/shared.pymodule that other_typesmodules can import from.src/datamodel_code_generator/_types/generate_config_dict.py (1)
14-154: Consider extracting duplicate Enum definitions to a shared module.All 13 Enum classes defined here (lines 14-154) are duplicated identically in
cli_config_dict.py. This creates maintenance overhead and potential inconsistencies. Consider extracting these common enums to a shared module (e.g.,_types/_common.pyor_types/enums.py) and importing them in both files.📋 Example refactoring approach
Create a new file
src/datamodel_code_generator/_types/_common_enums.py:# Common enums used across generated config TypedDicts from enum import Enum class AllExportsCollisionStrategy(Enum): error = "error" minimal_prefix = "minimal-prefix" full_prefix = "full-prefix" # ... rest of enumsThen update the generation process to import from the shared module instead of regenerating enums in each file.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
pyproject.tomlsrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
🚧 Files skipped from review as they are similar to previous changes (1)
- pyproject.toml
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.py
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.py
📚 Learning: 2025-12-18T13:35:21.591Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: .coderabbit.yaml:4-6
Timestamp: 2025-12-18T13:35:21.591Z
Learning: CodeRabbit's Ruff tool configuration supports the `config_file` property in `.coderabbit.yaml` to specify the path to the Ruff configuration file (e.g., "pyproject.toml", "ruff.toml", or ".ruff.toml"), as documented at https://docs.coderabbit.ai/tools#configuration-methods.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/_types/parse_config_dict.py (3)
src/datamodel_code_generator/_types/cli_config_dict.py (3)
AllExportsCollisionStrategy(14-17)AllExportsScope(20-22)ModuleSplitMode(101-102)src/datamodel_code_generator/_types/generate_config_dict.py (3)
AllExportsCollisionStrategy(14-17)AllExportsScope(20-22)ModuleSplitMode(105-106)src/datamodel_code_generator/config.py (1)
ParseConfig(726-745)
src/datamodel_code_generator/_types/generate_config_dict.py (3)
src/datamodel_code_generator/_types/parse_config_dict.py (3)
AllExportsCollisionStrategy(14-17)AllExportsScope(20-22)ModuleSplitMode(25-26)src/datamodel_code_generator/_types/parser_config_dict.py (14)
AllOfMergeMode(14-17)CollapseRootModelsNameStrategy(20-22)DataclassArguments(25-35)DateClassType(38-41)DatetimeClassType(44-49)FieldTypeCollisionStrategy(52-54)Formatter(57-61)LiteralType(64-67)NamingStrategy(70-74)PythonVersion(77-82)ReadOnlyWriteOnlyModelType(85-87)ReuseScope(90-92)StrictTypes(95-100)TargetPydanticVersion(103-105)src/datamodel_code_generator/config.py (1)
GenerateConfig(328-460)
⏰ 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: py312-isort7 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-black24 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (3)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
1-218: LGTM! Generated TypedDict definitions are well-formed.The generated type definitions provide a comprehensive typed configuration surface. All Enum and TypedDict structures are correctly formed, with proper use of
NotRequiredfor optional fields and appropriate type annotations throughout.src/datamodel_code_generator/_types/parse_config_dict.py (1)
29-36: LGTM! ParseConfig TypedDict is well-formed.The TypedDict structure correctly mirrors the ParseConfig model in config.py with proper use of
NotRequiredfor all optional fields.src/datamodel_code_generator/_types/cli_config_dict.py (1)
121-121: This file is auto-generated and should not be manually edited.The
ParseResultTypeAlias incli_config_dict.pyis automatically generated by datamodel-code-generator (see file header and pyproject.toml configuration). The loose typing (tuple[Any, Any, Any, Any, Any, Any]) results from how the tool convertsurllib.parse.ParseResult(a NamedTuple) to TypedDict format, which cannot directly represent named fields.If typing improvements are needed, address the source definition in
config.py:CliConfigSchemaor adjust the generation configuration inpyproject.toml—do not manually edit the generated file, as changes will be overwritten on regeneration.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
144-144: Import UnionMode and regenerate to fix type annotation.The
union_modefield is typed asAnybut should beUnionMode | Noneto match the sourceGenerateConfigmodel. Thepyproject.tomlconfiguration includesUnionModeintype_overrides(line 264), so adding the import and regenerating should resolve this.Required import
Add to imports section:
from datamodel_code_generator.model.pydantic_v2 import UnionModeThen regenerate using the configured profile:
datamodel-codegen --profile generate-config-dict
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
pyproject.tomlsrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/datamodel_code_generator/_types/parse_config_dict.py
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/_types/cli_config_dict.py
📚 Learning: 2025-12-18T13:35:21.591Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: .coderabbit.yaml:4-6
Timestamp: 2025-12-18T13:35:21.591Z
Learning: CodeRabbit's Ruff tool configuration supports the `config_file` property in `.coderabbit.yaml` to specify the path to the Ruff configuration file (e.g., "pyproject.toml", "ruff.toml", or ".ruff.toml"), as documented at https://docs.coderabbit.ai/tools#configuration-methods.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
🧬 Code graph analysis (3)
src/datamodel_code_generator/_types/generate_config_dict.py (6)
src/datamodel_code_generator/enums.py (15)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)GraphQLScope(155-158)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)TargetPydanticVersion(181-189)StrictTypes(199-206)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/_types/cli_config_dict.py (1)
DataclassArguments(32-42)src/datamodel_code_generator/_types/parser_config_dict.py (1)
DataclassArguments(26-36)src/datamodel_code_generator/config.py (1)
GenerateConfig(328-460)
src/datamodel_code_generator/_types/parser_config_dict.py (2)
src/datamodel_code_generator/enums.py (7)
AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)FieldTypeCollisionStrategy(105-113)NamingStrategy(116-128)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)TargetPydanticVersion(181-189)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)
src/datamodel_code_generator/_types/cli_config_dict.py (3)
src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/_types/generate_config_dict.py (1)
DataclassArguments(33-43)
🪛 GitHub Actions: Lint
src/datamodel_code_generator/_types/generate_config_dict.py
[error] 1-1: Ruff formatting check failed. 71 errors fixed by pre-commit hooks.
src/datamodel_code_generator/_types/parser_config_dict.py
[error] 1-1: Ruff formatting check failed. 71 errors fixed by pre-commit hooks.
src/datamodel_code_generator/_types/cli_config_dict.py
[error] 1-1: Ruff formatting check failed. 71 errors fixed by pre-commit hooks.
⏰ 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: 3.11 on macOS
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (3)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
1-149: Formatting addressed; structure looks good.Per the past review comments, the formatting issues reported by the pipeline have been addressed in commits 8c02562 to 92d41b8. The generated TypedDict structure is correct with proper imports and type annotations.
src/datamodel_code_generator/_types/generate_config_dict.py (1)
1-143: Structure and imports are correct.The generated TypedDict provides comprehensive configuration typing with proper enum imports and NotRequired fields. Formatting has been addressed per previous commits.
Also applies to: 145-166
src/datamodel_code_generator/_types/cli_config_dict.py (1)
1-147: Structure and typing surface are comprehensive.The generated TypedDict provides extensive CLI configuration typing with proper enum references and NotRequired fields. The
ParseResultTypeAlias andDataclassArgumentsdefinitions are correctly structured. Formatting has been addressed per previous commits.Also applies to: 149-171
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
28-38: Consider consolidating duplicated DataclassArguments TypedDict.The
DataclassArgumentsTypedDict is identical to the one incli_config_dict.py. Since both files are generated, this duplication might be intentional for module independence. However, if the code generator supports it, consider consolidating this into a single shared definition to follow DRY principles and prevent potential inconsistencies.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
🚧 Files skipped from review as they are similar to previous changes (3)
- src/datamodel_code_generator/_types/parse_config_dict.py
- src/datamodel_code_generator/_types/cli_config_dict.py
- src/datamodel_code_generator/_types/generate_config_dict.py
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
📚 Learning: 2025-12-18T13:35:21.591Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: .coderabbit.yaml:4-6
Timestamp: 2025-12-18T13:35:21.591Z
Learning: CodeRabbit's Ruff tool configuration supports the `config_file` property in `.coderabbit.yaml` to specify the path to the Ruff configuration file (e.g., "pyproject.toml", "ruff.toml", or ".ruff.toml"), as documented at https://docs.coderabbit.ai/tools#configuration-methods.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
🧬 Code graph analysis (1)
src/datamodel_code_generator/_types/parser_config_dict.py (4)
src/datamodel_code_generator/enums.py (7)
AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)FieldTypeCollisionStrategy(105-113)NamingStrategy(116-128)ReadOnlyWriteOnlyModelType(161-169)TargetPydanticVersion(181-189)StrictTypes(199-206)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/_types/cli_config_dict.py (1)
DataclassArguments(34-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (2)
src/datamodel_code_generator/_types/parser_config_dict.py (2)
41-151: LGTM: Comprehensive configuration TypedDict.The
ParserConfigTypedDict provides a well-structured, type-safe configuration surface with 110 fields covering all aspects of the parser configuration. The type annotations are correct and align with the enum definitions shown in the codebase.
25-25: No action required. The import ofStrictTypesfromdatamodel_code_generator.typesis correct. Thetypesmodule provides lazy access toStrictTypes(defined inenums.py) via its__getattr__function for backward compatibility, making the import valid and intentional.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/datamodel_code_generator/__main__.py (1)
175-188: Surface clear error messages for malformed extra_template_data / aliases / custom_formatters_kwargsRight now, three validation paths fail with a bare
Exit.ERRORand no user‑visible message:
- Building
extra_template_data = defaultdict(dict, **config.extra_template_data)when the structure is invalid.aliasesnot being adict[str, str].custom_formatters_kwargsnot being adict[str, str].This leaves users with an unexplained exit code, which has already been flagged in earlier reviews.
You can keep the new typed config flow and still print a concise error to stderr before returning, e.g.:
Example adjustments
else: - try: - extra_template_data = defaultdict(dict, **config.extra_template_data) - except (TypeError, ValueError): - return Exit.ERROR + try: + extra_template_data = defaultdict(dict, **config.extra_template_data) + except (TypeError, ValueError) as e: + print(f"Error: invalid extra_template_data: {e}", file=sys.stderr) # noqa: T201 + return Exit.ERROR if config.aliases is None: aliases = None else: aliases = config.aliases if not isinstance(aliases, dict) or not all( isinstance(k, str) and isinstance(v, str) for k, v in aliases.items() ): - return Exit.ERROR + print("Error: aliases must be a dict[str, str]", file=sys.stderr) # noqa: T201 + return Exit.ERROR if config.custom_formatters_kwargs is None: custom_formatters_kwargs = None else: custom_formatters_kwargs = config.custom_formatters_kwargs if not isinstance(custom_formatters_kwargs, dict) or not all( isinstance(k, str) and isinstance(v, str) for k, v in custom_formatters_kwargs.items() ): - return Exit.ERROR + print( + "Error: custom_formatters_kwargs must be a dict[str, str]", + file=sys.stderr, + ) # noqa: T201 + return Exit.ERRORThis keeps the behavior the same while making failures debuggable.
Also applies to: 1117-1151
🧹 Nitpick comments (4)
src/datamodel_code_generator/config.py (1)
76-326: De‑duplicate config TypedDict definitions with the_typespackage to avoid drift
GenerateConfigDict,ParserConfigDict, andParseConfigDicthere mirror the shapes already exposed underdatamodel_code_generator._types.*. Maintaining two sets of nearly identical TypedDicts will be easy to desync when fields are added/renamed.If feasible, consider reusing the
_typesdefinitions (e.g., via re-export or a shared stub module) instead of redefining them here, or at least adding a brief comment tying these to the corresponding_typesmodules so future changes are applied consistently.src/datamodel_code_generator/__main__.py (2)
567-585: Clarify merge semantics and make the MsgspecStruct special‑case robust to value typesIn
Config.merge_args:
set_argstreats anyNamespacevalue that is notNoneas “set”, which relies on all CLI defaults beingNonewhen the user does not pass the option. If any options usestore_true/store_falseor non‑None defaults, pyproject.toml values will be silently overridden by argparse defaults.- The
output_model_typespecial‑case checksset_args.get("output_model_type") == DataModelType.MsgspecStruct.value, which assumesoutput_model_typeis a string. If the parser ever yields aDataModelTypeenum instance instead, this comparison will never be true anduse_annotatedwon’t be auto‑enabled.Consider tightening this:
- Ensure the arg parser uses
default=Nonefor options that should not override pyproject values unless explicitly provided, so thevalue is not Nonecheck does what you expect.- Make the MsgspecStruct check tolerant of both strings and enums, e.g.:
Proposed tweak
- if set_args.get("output_model_type") == DataModelType.MsgspecStruct.value: + omt = set_args.get("output_model_type") + if omt in {DataModelType.MsgspecStruct, DataModelType.MsgspecStruct.value}: set_args["use_annotated"] = True
630-641: Be explicit about_extract_additional_importsmutatingextra_template_data
_extract_additional_imports()pulls"additional_imports"out of eachextra_template_dataentry usingpop(), andmain()then passes the mutatedextra_template_dataon to generation.If templates or other code paths were previously relying on
extra_template_data[...]["additional_imports"]being present at render time, this will change behavior. If the intent is to normalize those values intoconfig.additional_importsand hide them from templates, it’s worth:
- Adding a short comment here to document that this helper is intentionally destructive, or
- Switching to a non‑destructive read (
get) and leaving the key in place if you still want templates to see it.Given how subtle config/template interactions can be, I’d recommend double‑checking existing templates before relying on the destructive behavior.
Also applies to: 1117-1133
src/datamodel_code_generator/parser/base.py (1)
720-725: Simplify extra_template_data defaulting to avoid redundant defaultdict allocationsIn
Parser.__init__you normalizeextra_template_datato adefaultdict(dict)and then later do:self.extra_template_data: defaultdict[str, Any] = extra_template_data or defaultdict(dict)Because an empty
defaultdictis falsy, theorexpression always creates a seconddefaultdictin the “None → new defaultdict” case, discarding the first one.Functionally this is harmless, but you can simplify and avoid the extra allocation by assigning directly:
Possible simplification
- if extra_template_data is None: - extra_template_data = defaultdict(dict) - elif not isinstance(extra_template_data, defaultdict): - extra_template_data = defaultdict(dict, extra_template_data) + if extra_template_data is None: + extra_template_data = defaultdict(dict) + elif not isinstance(extra_template_data, defaultdict): + extra_template_data = defaultdict(dict, extra_template_data) ... - self.extra_template_data: defaultdict[str, Any] = extra_template_data or defaultdict(dict) + self.extra_template_data: defaultdict[str, Any] = extra_template_dataThis keeps behavior the same while making the intent clearer.
Also applies to: 905-908
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
pyproject.tomlsrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/config.pysrc/datamodel_code_generator/parser/base.py
🚧 Files skipped from review as they are similar to previous changes (1)
- pyproject.toml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/parser/base.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.py
🧬 Code graph analysis (3)
src/datamodel_code_generator/config.py (4)
src/datamodel_code_generator/enums.py (1)
AllExportsCollisionStrategy(92-102)src/datamodel_code_generator/format.py (2)
DateClassType(60-65)DatetimeClassType(50-57)src/datamodel_code_generator/model/pydantic_v2/__init__.py (1)
ConfigDict(29-55)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)
src/datamodel_code_generator/parser/base.py (3)
src/datamodel_code_generator/types.py (2)
DataType(296-780)DataTypeManager(832-910)src/datamodel_code_generator/config.py (4)
ParseConfig(726-745)ParseConfigDict(316-325)ParserConfig(601-723)_rebuild_config_models(751-786)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(17-24)
src/datamodel_code_generator/__main__.py (5)
src/datamodel_code_generator/config.py (6)
GenerateConfig(328-460)Config(335-339)Config(470-474)Config(608-612)Config(733-737)_rebuild_config_models(751-786)src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfig(48-168)src/datamodel_code_generator/util.py (2)
model_dump(254-258)model_validate(261-265)src/datamodel_code_generator/model/pydantic/__init__.py (1)
Config(26-47)src/datamodel_code_generator/__init__.py (4)
Error(298-307)generate(452-456)generate(460-463)generate(466-862)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
754-754: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
755-755: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
757-757: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
758-758: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
761-761: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/base.py
691-691: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
699-699: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3107-3107: Unused noqa directive (non-enabled: PLR0914)
Remove unused noqa directive
(RUF100)
3114-3114: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3117-3117: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__main__.py
42-42: Unused noqa directive (non-enabled: TC003)
Remove unused noqa directive
(RUF100)
175-175: Unused noqa directive (non-enabled: N805)
Remove unused noqa directive
(RUF100)
500-500: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
501-501: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
503-503: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
504-504: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
505-505: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
587-587: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
727-727: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
729-729: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
748-748: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
750-750: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
751-751: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1022-1022: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1029-1029: Unused noqa directive (non-enabled: T201)
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). (12)
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: 3.12 on Ubuntu
- GitHub Check: py312-isort6 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (4)
src/datamodel_code_generator/config.py (1)
748-786: Forward‑ref rebuild logic for config models looks correct and idempotentThe
_rebuild_config_models()helper cleanly centralizes forward‑ref resolution for all four config models, with:
- A simple
_CONFIG_MODELS_STATE["built"]guard to avoid repeated rebuilds.- Lazy, in‑function imports of heavy/cyclic types (
Path,DataModel,DataTypeManager,UnionMode) so module import stays cheap and cycles are mitigated.- Version‑aware branching between
model_rebuild(_types_namespace=...)for Pydantic v2 andupdate_forward_refs(**types_namespace)for v1.This matches the project’s existing lazy‑import pattern (including the intentional
# noqa: PLC0415on these imports), and should keep both runtimes aligned without extra work for callers that just need to importGenerateConfig/ParserConfig/ParseConfig/CliConfigSchema.src/datamodel_code_generator/__main__.py (1)
587-627: Config → GenerateConfig translation looks correct; verify settings_path semantics
Config.to_generate_config()plusrun_generate_from_config()nicely centralize the mapping from CLI/pyproject options into aGenerateConfiginstance, including:
- Dropping CLI‑only keys (
input,url,check,watch, etc.).- Translating
use_default/force_optionalinto the correspondingGenerateConfigflags.- Allowing validated dicts for
extra_template_data,aliases, andcustom_formatters_kwargs.One point to double‑check:
run_generate_from_configalways passessettings_path=config.outputintoto_generate_config, which then feedsGenerateConfig.settings_path. If earlier behavior allowed an explicit “formatter settings path” independent of--output, or used a different default, this might change whereCodeFormatterlooks for config files.If that behavior change is intentional, it’d be good to mention it in release notes; if not, consider adding a dedicated CLI/config option for
settings_pathand wiring that through instead of overloadingoutput.Also applies to: 940-959
src/datamodel_code_generator/parser/base.py (2)
72-87: Parser now cleanly accepts either a ParserConfig model or unpacked optionsThe refactored
Parser.__init__signature:def __init__(..., *, config: ParserConfig | None = None, **options: Unpack[ParserConfigDict]) -> None:combined with:
- The
_rebuild_config_models()call before anyParserConfigusage, and- The
config is not None and optionsguard, followed bymodel_validate(ParserConfig, ...)gives a clear, version‑agnostic way to construct parser instances from either a fully‑typed config object or the old
**optionsstyle.This should make the public API easier to evolve while keeping Pydantic v1/v2 compatibility encapsulated in
model_validateand_rebuild_config_models.Also applies to: 691-710
2794-2838: ParseSettings abstraction and config‑driven parse() flow look consistentThe introduction of
ParseSettingsand its use across:
_prepare_parse_config()(computingwith_import,use_deferred_annotations, andcode_formatter),_process_single_module()(usingconfig.use_deferred_annotations),_generate_module_output()/_generate_empty_init_exports()(drivingall_exports_scope/collision behavior and formatting),plus the new
parse()signature that acceptsconfig: ParseConfigModel | Noneor**options: Unpack[ParseConfigDict]and feeds those into_prepare_parse_config(), gives a coherent, single‑source‑of‑truth configuration for parsing.The pattern mirrors the ParserConfig handling in
__init__and keeps Pydantic v1/v2 details behindmodel_validateand_rebuild_config_models, which should make future config evolution more manageable.Also applies to: 3000-3036, 3072-3105, 3107-3195
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/datamodel_code_generator/_types/cli_config_dict.py (2)
46-46: Consider making ParseResult more specific.The 6-tuple of
Anyis very generic. If the tuple positions have known semantic meanings (e.g., url parts, query params), consider documenting them or using a more descriptive TypedDict instead of a tuple.
33-43: DataclassArguments is duplicated across generated files.This TypedDict appears in both
cli_config_dict.pyandparser_config_dict.py. While duplication in generated files is acceptable since they're regenerated together, consider whether a shared_types/common.pymodule would reduce redundancy and make the structure clearer.pyproject.toml (1)
268-268: Consider multiline formatting for long type_overrides.The
type_overridesdictionaries are very long (150+ characters), making them hard to read and maintain. TOML supports multiline inline tables for better readability.Example multiline format
type_overrides = { AllExportsCollisionStrategy = "datamodel_code_generator.enums.AllExportsCollisionStrategy", AllExportsScope = "datamodel_code_generator.enums.AllExportsScope", # ... more entries UnionMode = "datamodel_code_generator.model.pydantic_v2.UnionMode", }Also applies to: 277-277, 295-295
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
pyproject.tomlsrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/datamodel_code_generator/_types/parse_config_dict.py
- src/datamodel_code_generator/_types/generate_config_dict.py
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.py
📚 Learning: 2025-12-18T13:35:21.591Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2681
File: .coderabbit.yaml:4-6
Timestamp: 2025-12-18T13:35:21.591Z
Learning: CodeRabbit's Ruff tool configuration supports the `config_file` property in `.coderabbit.yaml` to specify the path to the Ruff configuration file (e.g., "pyproject.toml", "ruff.toml", or ".ruff.toml"), as documented at https://docs.coderabbit.ai/tools#configuration-methods.
Applied to files:
src/datamodel_code_generator/_types/parser_config_dict.py
🧬 Code graph analysis (2)
src/datamodel_code_generator/_types/cli_config_dict.py (4)
src/datamodel_code_generator/enums.py (3)
AllExportsScope(81-89)AllOfMergeMode(142-152)FieldTypeCollisionStrategy(105-113)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/_types/generate_config_dict.py (1)
DataclassArguments(34-44)
src/datamodel_code_generator/_types/parser_config_dict.py (4)
src/datamodel_code_generator/enums.py (8)
AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)FieldTypeCollisionStrategy(105-113)NamingStrategy(116-128)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)TargetPydanticVersion(181-189)StrictTypes(199-206)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/config.py (1)
ParserConfig(601-723)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Analyze (python)
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: benchmarks
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.10 on macOS
🔇 Additional comments (4)
src/datamodel_code_generator/_types/parser_config_dict.py (1)
1-149: Generated TypedDict structure is appropriate.The TypedDict conversion from the Pydantic ParserConfig model appropriately simplifies complex types (Mapping → dict, Sequence → list, custom schema types → str/Any) to standard Python types that TypedDict supports. The
Anytypes for model class references (lines 40-43) are necessary since type objects cannot be precisely represented in TypedDict without complex TYPE_CHECKING imports.src/datamodel_code_generator/_types/cli_config_dict.py (1)
28-28: UnionMode import and typing are correct.The UnionMode type is properly imported (line 28) and used (line 149), resolving the previously flagged typing issue.
Also applies to: 149-149
pyproject.toml (2)
246-250: Coverage exclusion for generated files is appropriate.Excluding
src/datamodel_code_generator/_types/*from coverage is correct since these are generated TypedDict files that don't require test coverage.
265-299: Profile configurations are well-structured and consistent.The four datamodel-codegen profiles are properly configured with appropriate type overrides, formatters, and output paths. The UnionMode type override is correctly included in the relevant profiles (generate-config-dict, parser-config-dict, cli-config-dict).
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/datamodel_code_generator/config.py (1)
507-542: Lazy forward-ref rebuilding and# noqa: PLC0415are appropriate hereThe
_rebuild_config_models()helper correctly centralizes the forward-ref resolution for all four config models using_types_namespaceand switches betweenmodel_rebuild(v2) andupdate_forward_refs(v1). The local imports guarded by# noqa: PLC0415are intentionally lazy to break cycles withmodel.baseandtypes, and per prior project learnings thosePLC0415markers should be kept even though Ruff’s RUF100 flags them as “unused” today.src/datamodel_code_generator/parser/base.py (1)
1736-1783: Lazy DataType import + PLC0415noqashould be retainedThe on-demand
from datamodel_code_generator.types import DataType # noqa: PLC0415inside__collapse_root_modelsavoids a heavy import (and potential cycles) for callers that don’t usecollapse_root_models. Keeping thePLC0415noqahere matches the project convention of explicitly allowing lazy imports, even if Ruff’s RUF100 currently reports it as “unused”.
🧹 Nitpick comments (2)
src/datamodel_code_generator/parser/base.py (1)
691-827: Config-driven Parser.init is sound; note breaking “config + options” combinationThe refactored
Parser.__init__correctly:
- Enforces mutual exclusivity between
configand**optionswith a clearValueError.- Validates both dict-style options and pre-built objects via
model_validate(parser_config_model, …).- Normalizes
extra_template_datato adefaultdict(dict)and wires all ParserConfig fields onto instance attributes with unchanged semantics.This is a behaviour change for callers that previously mixed explicit kwargs with a config-like object; worth documenting, but the implementation itself looks solid.
src/datamodel_code_generator/_types/generate_config_dict.py (1)
36-169: Generated GenerateConfig TypedDict matches the Pydantic model and JSON-friendly containers
DataclassArgumentsandGenerateConfighere mirror the fields and high-level types ofGenerateConfiginconfig.py, while appropriately using JSON/CLI-friendly containers (list/dictinstead ofSequence/Mapping/set) and optional Path/enum types under TYPE_CHECKING. Given this file is generated, the current shape looks correct; any future tweaks should come from updating the generator/schema rather than hand-editing the TypedDict.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/config.pysrc/datamodel_code_generator/parser/base.py
🚧 Files skipped from review as they are similar to previous changes (3)
- src/datamodel_code_generator/_types/cli_config_dict.py
- src/datamodel_code_generator/_types/parser_config_dict.py
- src/datamodel_code_generator/_types/parse_config_dict.py
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/parser/base.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.py
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/generate_config_dict.py
🧬 Code graph analysis (3)
src/datamodel_code_generator/config.py (3)
src/datamodel_code_generator/_types/generate_config_dict.py (2)
DataclassArguments(36-46)GenerateConfig(49-169)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(17-24)
src/datamodel_code_generator/_types/generate_config_dict.py (4)
src/datamodel_code_generator/enums.py (16)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)AllOfMergeMode(142-152)CollapseRootModelsNameStrategy(131-139)DataModelType(48-56)FieldTypeCollisionStrategy(105-113)GraphQLScope(155-158)InputFileType(35-45)ModuleSplitMode(172-178)NamingStrategy(116-128)OpenAPIScope(70-78)ReadOnlyWriteOnlyModelType(161-169)ReuseScope(59-67)TargetPydanticVersion(181-189)UnionMode(192-196)StrictTypes(199-206)src/datamodel_code_generator/format.py (4)
DateClassType(60-65)DatetimeClassType(50-57)Formatter(171-177)PythonVersion(68-140)src/datamodel_code_generator/parser/__init__.py (1)
LiteralType(20-25)src/datamodel_code_generator/config.py (1)
GenerateConfig(84-216)
src/datamodel_code_generator/parser/base.py (3)
src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(17-24)src/datamodel_code_generator/config.py (3)
ParseConfig(482-501)ParserConfig(357-479)_rebuild_config_models(507-542)src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(41-151)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
510-510: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
511-511: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
513-513: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
514-514: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
517-517: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/parser/base.py
691-691: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
699-699: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
702-702: Unused noqa directive (non-enabled: SLF001)
Remove unused noqa directive
(RUF100)
1736-1736: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3112-3112: Unused noqa directive (non-enabled: PLR0914)
Remove unused noqa directive
(RUF100)
3119-3119: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
3122-3122: Unused noqa directive (non-enabled: SLF001)
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: 3.10 on Windows
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.13 on macOS
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.11 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (9)
src/datamodel_code_generator/config.py (3)
84-217: Unified GenerateConfig model looks consistent with existing optionsThe
GenerateConfigBaseModel mirrors the existing generator options well (types/defaults align with the new TypedDict surface and existing CLI flags), andextra="forbid"/arbitrary_types_allowed=Trueis an appropriate balance here. I don’t see behavioural regressions in how generator options are modeled.
219-355: CliConfigSchema separation keeps CLI schema concerns isolatedDefining
CliConfigSchemaas a separate BaseModel (rather than reusingGenerateConfig) is a sensible split between “CLI surface” and “generator core” while still sharing enum/types. The config, defaults, and stricterextra="forbid"settings look appropriate for validating CLI-derived config.
357-502: ParserConfig / ParseConfig shapes match parser usage
ParserConfigandParseConfigline up with howParser.__init__()andParser.parse()consume configuration (data_model types, re-use controls, exports settings, split mode, etc.), and using the same v1/v2 pattern (model_configvs nestedConfig) keeps compatibility tidy. This should make the new config-driven entry points predictable and type-safe.src/datamodel_code_generator/parser/base.py (6)
71-87: TYPE_CHECKING imports and util helpers align with new config modelsThe added
model_copy,model_dump, andmodel_validateimports plus TYPE_CHECKING-only aliases (ParseConfigModel,ParseConfigDict,ParserConfig,ParserConfigDict,DataType,DataTypeManager,Unpack) correctly describe the new config-driven surface without affecting runtime import order. This keeps type-checkers happy while deferring actual config module loading to the lazy imports further down.
128-137: ParseSettings NamedTuple cleanly encapsulates parse-time options
ParseSettingscaptures just the knobs actually needed during module/code-generation (with_import, deferred annotations, formatter, exports scope/collision strategy, split mode). Using this small immutable object simplifies passing settings through_process_single_module,_generate_module_output, and_generate_empty_init_exportswithout further bloating method signatures.
2799-2843: _prepare_parse_config → ParseSettings wiring preserves previous semantics
_prepare_parse_confignow returnsParseSettings, computing:
use_deferred_annotationsusing the same combination of Python version,with_import, anddisable_future_imports.- Optional
CodeFormatteronly whenformat_is truthy.- A normalized boolean
with_import=bool(with_import)for downstream checks.This keeps the old behaviour while making the parser pipeline consume a single settings object instead of a pile of discrete parameters.
2917-2975: Propagating ParseSettings into _process_single_module is a good encapsulationPlumbing
config: ParseSettingsinto_process_single_moduleand usingconfig.use_deferred_annotationsfor sorting ensures module-level processing has just the knobs it needs without re-reading top-level Parser attributes. The rest of the method remains behaviourally identical.
3005-3111: _generate_module_output / _generate_empty_init_exports correctly consult ParseSettingsBoth
_generate_module_outputand_generate_empty_init_exportsnow:
- Use
config.all_exports_scope/config.all_exports_collision_strategyinstead of separate parameters.- Respect
config.with_importwhen deciding whether to emit imports.- Run
config.code_formatterif present.That keeps all exports and formatting behaviour governed strictly by the config models, matching the new ParseSettings design.
3112-3198: parse() now mirrors init’s config/kwargs contract and centralizes validationThe new
parse()implementation:
- Lazily imports the
configmodule and calls_rebuild_config_models()to ensure forward refs are ready.- Enforces the same “either
configor**options, not both” rule as__init__.- Uses
model_validate(parse_config_model, …)for both dict and object inputs, then passes the resulting values into_prepare_parse_config.- Relies on the resulting
parse_settingsthroughout the rest of the pipeline (module structure, generation, empty-init exports).This gives a consistent, strongly-typed story for parse-time configuration without altering the actual parsing/generation algorithm.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/datamodel_code_generator/__init__.py (1)
892-927: Consider adding*Dictvariants to__all__for consistency.The
__getattr__function exposesGenerateConfigDict,ParserConfigDict, andParseConfigDict, but these are not listed in__all__. This means:
- Direct imports work:
from datamodel_code_generator import GenerateConfigDict✓- Star imports won't include them:
from datamodel_code_generator import *✗If these are intended as public API, consider adding them to
__all__:"GenerateConfigDict", "ParserConfigDict", "ParseConfigDict",
📜 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/cli_config_dict.pysrc/datamodel_code_generator/_types/generate_config_dict.pysrc/datamodel_code_generator/_types/parse_config_dict.pysrc/datamodel_code_generator/_types/parser_config_dict.pysrc/datamodel_code_generator/config.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/datamodel_code_generator/_types/parser_config_dict.py
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.pysrc/datamodel_code_generator/__init__.py
📚 Learning: 2025-12-18T13:43:16.235Z
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.
Applied to files:
src/datamodel_code_generator/_types/cli_config_dict.pysrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/_types/generate_config_dict.py
🧬 Code graph analysis (5)
src/datamodel_code_generator/_types/parse_config_dict.py (2)
src/datamodel_code_generator/enums.py (3)
AllExportsCollisionStrategy(92-102)AllExportsScope(81-89)ModuleSplitMode(172-178)src/datamodel_code_generator/config.py (1)
ParseConfig(545-578)
src/datamodel_code_generator/config.py (6)
src/datamodel_code_generator/_types/generate_config_dict.py (2)
DataclassArguments(34-44)GenerateConfig(47-167)src/datamodel_code_generator/_types/parser_config_dict.py (2)
DataclassArguments(26-36)ParserConfig(39-149)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/model/__init__.py (1)
DataModelSet(25-35)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(15-22)src/datamodel_code_generator/__main__.py (1)
Config(143-627)
src/datamodel_code_generator/_types/cli_config_dict.py (3)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
DataclassArguments(34-44)src/datamodel_code_generator/_types/parser_config_dict.py (1)
DataclassArguments(26-36)src/datamodel_code_generator/config.py (1)
CliConfigSchema(220-355)
src/datamodel_code_generator/__init__.py (5)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfig(47-167)src/datamodel_code_generator/config.py (6)
GenerateConfig(85-217)ParseConfig(545-578)ParserConfig(358-542)_rebuild_config_models(584-619)_from_generate_config(483-542)_from_generate_config(567-578)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(15-22)src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(39-149)src/datamodel_code_generator/format.py (3)
Formatter(171-177)CodeFormatter(183-421)format_directory(406-421)
src/datamodel_code_generator/_types/generate_config_dict.py (3)
src/datamodel_code_generator/_types/cli_config_dict.py (1)
DataclassArguments(33-43)src/datamodel_code_generator/_types/parser_config_dict.py (1)
DataclassArguments(26-36)src/datamodel_code_generator/config.py (1)
GenerateConfig(85-217)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
492-492: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
587-587: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
588-588: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
590-590: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
591-591: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
594-594: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__init__.py
74-74: Unused noqa directive (non-enabled: E402)
Remove unused noqa directive
(RUF100)
468-468: Unused noqa directive (non-enabled: PLR0912, PLR0914, PLR0915)
Remove unused noqa directive
(RUF100)
485-485: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
510-510: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
616-616: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
688-688: Unused noqa directive (non-enabled: SLF001)
Remove unused noqa directive
(RUF100)
702-702: Unused noqa directive (non-enabled: SLF001)
Remove unused noqa directive
(RUF100)
873-873: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
877-877: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
882-882: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
884-884: 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-black24 on Ubuntu
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.10 on macOS
- GitHub Check: 3.11 on macOS
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.14 on Windows
- GitHub Check: Analyze (python)
- GitHub Check: benchmarks
🔇 Additional comments (10)
src/datamodel_code_generator/_types/generate_config_dict.py (1)
1-167: Generated TypedDict structure looks correct.The
DataclassArgumentsandGenerateConfigTypedDicts are well-structured and align with the corresponding Pydantic models inconfig.py. The field types appropriately useNotRequiredfor optional fields and reference the correct enum types.Note: The cyclic import from
datamodel_code_generator.types(line 31) was previously flagged by static analysis. This appears to be an accepted pattern in this codebase for generated type stubs.src/datamodel_code_generator/_types/cli_config_dict.py (2)
46-46:ParseResultTypeAlias simplification is appropriate for serialization.The
tuple[Any, Any, Any, Any, Any, Any]representation ofParseResultis a reasonable simplification for JSON/CLI serialization contexts. The actualurllib.parse.ParseResultis a named tuple with 6 elements, so this preserves the structure while avoiding complex type dependencies in the generated TypedDict.
49-172:CliConfigSchemaTypedDict is comprehensive and well-aligned.The TypedDict correctly mirrors the
CliConfigSchemaPydantic model inconfig.py, including CLI-specific fields (check,debug,disable_warnings,watch,watch_delay,url) that differentiate it fromGenerateConfig.src/datamodel_code_generator/_types/parse_config_dict.py (1)
1-22:ParseConfigTypedDict is correctly defined.The generated TypedDict is minimal and focused, containing only the parse-time configuration fields. It correctly aligns with the
ParseConfigPydantic model inconfig.py.src/datamodel_code_generator/config.py (3)
48-56: Runtime type fallbacks for Pydantic v1 compatibility.The pattern of setting types to
Anyfor Pydantic v1 runtime is appropriate. Note thatUnionModeis unconditionally set toAny(line 56) outside theis_pydantic_v2()check, which is intentional sinceUnionModeis only available in the pydantic_v2 module and may not be importable at all in some environments.
482-542:ParserConfig._from_generate_configconversion logic is sound.The method correctly:
- Builds effective
dataclass_argumentsfromfrozen_dataclassesandkeyword_onlyflags- Sets
enum_field_as_literaltoLiteralType.AllforTypingTypedDictoutput- Forces
set_default_enum_membertoTrueforDataclassesDataclassoutput- Computes
defer_formattingbased on output path having no suffix- Uses field intersection to safely copy overlapping config values
584-619: Forward reference rebuilding is correctly implemented.The
_rebuild_config_models()function properly handles:
- Singleton pattern via
_CONFIG_MODELS_STATEto avoid redundant rebuilds- Lazy imports of runtime types to break cyclic dependencies
UnionModeimport wrapped in try/except for environments without pydantic_v2- Both Pydantic v1 (
update_forward_refs) and v2 (model_rebuild) pathsRegarding the static analysis hints about unused
# noqa: PLC0415directives: Based on learnings, these defensive directives should be kept to prepare for potential future Ruff configuration changes that might enable the import-outside-top-level rule.src/datamodel_code_generator/__init__.py (3)
451-473: Function overloads provide good type safety for the dual API.The overload pattern correctly distinguishes between:
generate(input_, config=config)- using aGenerateConfigobjectgenerate(input_, **options)- using unpackedGenerateConfigDictkwargsThe implementation at lines 494-500 properly validates mutual exclusivity between
configandoptions.
688-704: Config-driven parser construction is clean and correct.The refactored flow:
- Creates
ParserConfigvia_from_generate_config()with computed values- Instantiates the parser with
config=parser_config- Creates
ParseConfigvia_from_generate_config()- Calls
parser.parse(config=parse_config)This centralizes configuration handling and ensures consistent parameter passing.
880-886: UnionMode fallback logic is correct and intentional.The implementation properly handles the pydantic v2
UnionModefeature with appropriate fallback. WhenUnionModecannot be imported frompydantic_v2, the code falls back toconfig.UnionMode, which is defined asAnyin non-pydantic-v2 environments (config.py line 56). This pattern mirrors the try/except logic in config.py itself and is the expected behavior sinceUnionModeis a pydantic v2-specific feature. No changes needed.
| all_exports_collision_strategy=all_exports_collision_strategy, | ||
| module_split_mode=module_split_mode, | ||
| if input_file_type == InputFileType.OpenAPI: | ||
| parser = OpenAPIParser( |
Check failure
Code scanning / CodeQL
Potentially uninitialized local variable Error
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix a “potentially uninitialized local variable” involving a class or function name in Python, ensure that the name is bound before use, and that it is bound in a way consistent with how it is being used (global vs. local). For parser classes like OpenAPIParser, GraphQLParser, and JsonSchemaParser, the intended scope is module-global: they should be imported from their respective modules at the top of __init__.py, not assigned inside the generate function.
The single best fix here, without changing behavior, is to add explicit imports for the parser classes at the module level along with the other imports. This makes them unambiguous global names and avoids any possibility that Python will treat them as locals or that they will be referenced before binding. We do not touch the logic that chooses which parser to instantiate; we only ensure that the classes are defined. Concretely, in src/datamodel_code_generator/__init__.py, in the imports area near the existing from datamodel_code_generator.parser import DefaultPutDict, LiteralType, we add imports for OpenAPIParser, GraphQLParser, and JsonSchemaParser from their respective modules under datamodel_code_generator.parser. No additional helper methods or external libraries are needed.
| @@ -56,6 +56,9 @@ | ||
| PythonVersionMin, | ||
| ) | ||
| from datamodel_code_generator.parser import DefaultPutDict, LiteralType | ||
| from datamodel_code_generator.parser.graphql import GraphQLParser | ||
| from datamodel_code_generator.parser.jsonschema import JsonSchemaParser | ||
| from datamodel_code_generator.parser.openapi import OpenAPIParser | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing_extensions import Unpack |
| use_status_code_in_response_name=config.use_status_code_in_response_name, | ||
| ) | ||
| elif input_file_type == InputFileType.GraphQL: | ||
| parser = GraphQLParser( |
Check failure
Code scanning / CodeQL
Potentially uninitialized local variable Error
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
Generally, this kind of issue is fixed by ensuring the variable/name is definitely bound before any possible use. For a class like GraphQLParser, that means adding an unconditional import at the module level (not inside if TYPE_CHECKING:) so that the name is always available when generate() runs and the GraphQL branch is taken.
The best fix here, without changing behavior, is to add a regular import for GraphQLParser alongside the other parser-related imports at the top of src/datamodel_code_generator/__init__.py. Since we are only allowed to edit shown snippets, we will add a new import line in the visible import section near the existing from datamodel_code_generator.parser import DefaultPutDict, LiteralType. A reasonable and conventional path is from datamodel_code_generator.parser.graphql import GraphQLParser, which introduces the missing symbol without touching the rest of the logic. No other code changes are needed: the elif input_file_type == InputFileType.GraphQL: block will then always see a properly initialized GraphQLParser name.
Concretely:
- Edit
src/datamodel_code_generator/__init__.pyin the import section around lines 58–59. - Add an explicit import statement for
GraphQLParserfrom its likely submodule. - Do not change existing imports or the parser construction logic around lines 683–702.
| @@ -56,6 +56,7 @@ | ||
| PythonVersionMin, | ||
| ) | ||
| from datamodel_code_generator.parser import DefaultPutDict, LiteralType | ||
| from datamodel_code_generator.parser.graphql import GraphQLParser | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing_extensions import Unpack |
| data_model_union_type=data_model_types.union_model, | ||
| ) | ||
| else: | ||
| parser = JsonSchemaParser( |
Check failure
Code scanning / CodeQL
Potentially uninitialized local variable Error
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, this kind of issue is fixed by ensuring that any variable or name used in a function is definitely bound before it is referenced. For parser classes like JsonSchemaParser, the right approach is to import them at module scope so they are always available when the generate-like function executes, rather than relying on conditional or implicit definitions.
Concretely, in src/datamodel_code_generator/__init__.py, we should add explicit imports for OpenAPIParser, GraphQLParser, and JsonSchemaParser from their respective modules at the top of the file, alongside the other datamodel_code_generator imports. This guarantees that JsonSchemaParser (and the other parsers) are defined in the module’s global scope before any call to this function, eliminating the possibility of an uninitialized local variable. No changes are required to the logic around the if/elif/else that selects the parser; only the imports need to be added.
Assuming the standard layout of this project, these classes live under datamodel_code_generator.parser.openapi, .graphql, and .jsonschema. We therefore add:
from datamodel_code_generator.parser.openapi import OpenAPIParserfrom datamodel_code_generator.parser.graphql import GraphQLParserfrom datamodel_code_generator.parser.jsonschema import JsonSchemaParser
near the other import statements at the top of the file. No additional helper methods or definitions are needed.
| @@ -56,6 +56,9 @@ | ||
| PythonVersionMin, | ||
| ) | ||
| from datamodel_code_generator.parser import DefaultPutDict, LiteralType | ||
| from datamodel_code_generator.parser.graphql import GraphQLParser | ||
| from datamodel_code_generator.parser.jsonschema import JsonSchemaParser | ||
| from datamodel_code_generator.parser.openapi import OpenAPIParser | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing_extensions import Unpack |
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/datamodel_code_generator/config.py (1)
76-82: Verify cyclic imports with _types modules are acceptable.CodeQL flagged cyclic imports involving the
_typessubmodules (lines 76-78). While the TYPE_CHECKING guards (lines 40-56) help with type-checking time, these module-level runtime imports may create actual circular dependencies if the_typesmodules import back fromconfig.py.Run the following to confirm the import order and dependencies:
#!/bin/bash # Check if _types modules import from config echo "=== Checking _types/generate_config_dict.py ===" rg -n "from.*config import" src/datamodel_code_generator/_types/generate_config_dict.py || echo "No imports from config" echo -e "\n=== Checking _types/parse_config_dict.py ===" rg -n "from.*config import" src/datamodel_code_generator/_types/parse_config_dict.py || echo "No imports from config" echo -e "\n=== Checking _types/parser_config_dict.py ===" rg -n "from.*config import" src/datamodel_code_generator/_types/parser_config_dict.py || echo "No imports from config" echo -e "\n=== Checking import structure ===" python -c "import sys; sys.path.insert(0, 'src'); import datamodel_code_generator.config" 2>&1 | head -20
🧹 Nitpick comments (1)
src/datamodel_code_generator/config.py (1)
220-356: Consider reducing duplication with GenerateConfig.
CliConfigSchemaduplicates most ofGenerateConfigwith a few additions (CLI-specific fields likecheck,debug,watch). While this works, consider whether inheritance or composition could reduce maintenance burden.Potential refactor approach
You could define a shared base class or use composition:
class SharedConfigFields(BaseModel): # Common fields here ... class GenerateConfig(SharedConfigFields): # Generate-specific fields ... class CliConfigSchema(SharedConfigFields): # CLI-specific fields input: Path | str | None = None check: bool = False ...This would make it easier to maintain consistency and avoid field drift between the two models.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/datamodel_code_generator/config.pytests/test_public_api_signature.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.py
🧬 Code graph analysis (1)
tests/test_public_api_signature.py (1)
src/datamodel_code_generator/parser/base.py (1)
Parser(684-3107)
🪛 GitHub Actions: Lint
tests/test_public_api_signature.py
[error] 9-9: ruff formatting failed: 1 error fixed, 0 remaining. The hook modified the file (docstring content) to conform to style.
🪛 GitHub Check: CodeQL
src/datamodel_code_generator/config.py
[notice] 47-47: Cyclic import
Import of module datamodel_code_generator.types begins an import cycle.
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
358-358: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
369-369: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
612-612: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
613-613: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
615-615: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
616-616: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
619-619: 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). (8)
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: Analyze (python)
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: benchmarks
🔇 Additional comments (7)
tests/test_public_api_signature.py (2)
11-39: LGTM! Comprehensive public API signature validation.The tests effectively validate backward compatibility by checking:
- Parameter presence and ordering
- Keyword-only constraint on
configparameter- Default value of
Noneforconfig- Presence of
**optionsfor backward compatibility- TypedDict runtime availability
1-9: Pipeline formatting issue auto-corrected.The ruff formatter modified this section to conform to style. Ensure the auto-formatted changes are committed.
⛔ 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:14.661Z 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.src/datamodel_code_generator/config.py (5)
85-218: LGTM! Well-structured configuration model.The
GenerateConfigmodel comprehensively covers all generation options with:
- Proper Pydantic v1/v2 compatibility handling
- Clear field definitions with appropriate defaults
- Good type annotations throughout
358-388: LGTM! Helper function correctly assembles parser configuration.The function effectively consolidates parser config overrides from various sources. The lazy import on line 369 with its defensive
# noqa: PLC0415aligns with the project's practice of keeping such directives for future-proofing.Based on learnings, defensive
# noqa: PLC0415directives should be retained.
390-568: LGTM! ParserConfig construction and transformation logic is sound.The
_from_generate_configclassmethod correctly:
- Derives effective configuration values based on model type
- Handles Pydantic v1/v2 field access differences
- Filters fields to common subset before merging overrides
- Validates the final configuration
570-604: LGTM! ParseConfig follows consistent pattern.The model and its
_from_generate_configmethod follow the same sound approach asParserConfig, maintaining consistency across the config transformation API.
609-644: LGTM! Forward reference resolution correctly handles v1/v2 differences.The function properly:
- Guards against multiple rebuilds with state tracking
- Uses lazy imports to defer loading (with defensive noqa directives per project convention)
- Builds appropriate types namespace for both Pydantic versions
- Handles ImportError for Pydantic v2-only types
The CodeQL warnings about cyclic imports on lines 615-616 are mitigated by placing these imports inside the function, breaking the cycle at module initialization time.
Based on learnings, the defensive
# noqa: PLC0415directives should be retained.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/datamodel_code_generator/config.py (1)
607-645: _rebuild_config_models safely resolves forward refs and UnionModeThe rebuild function:
- Short-circuits after the first call via
_CONFIG_MODELS_STATE.- Lazily imports Path/ParseResult/DataModel/DataTypeManager/etc. with
# noqa: PLC0415to keep lazy imports explicit (consistent with project learnings).- Handles missing
UnionModegracefully by falling back toAny.- Calls
model_rebuild(v2) orupdate_forward_refs(v1) on all four config models.This should address the cyclic-import concerns raised by previous scanners. I would keep the
# noqa: PLC0415comments here, in line with your existing pattern.Based on learnings, the Ruff RUF100 warnings for these
# noqa: PLC0415markers can be ignored; they are intentional for future-proofing lazy imports.
🧹 Nitpick comments (2)
src/datamodel_code_generator/config.py (1)
358-387: _build_parser_config_overrides: behavior looks correct, minor nit on noqaThe helper:
- Derives
base_pathonly wheninput_is aPathpointing to a file.- Wires in all
data_model_typescomponents.- Propagates
default_field_extrasand effective enum/dataclass settings.- Uses
defer_formattingwhenoutputis a directory-like path (suffix empty).All of that matches the parser pipeline. The
# noqa: PLR0913is currently reported as unused by Ruff in the static hints; if PLR0913 isn’t enabled in your config anymore, you can safely drop that directive.Please confirm against your current Ruff config whether PLR0913 is enabled; if not, removing the
# noqawill clear the RUF100 warning.src/datamodel_code_generator/__main__.py (1)
587-627: to_generate_config centralizes CLI → GenerateConfig translationThe helper:
- Dumps
selfto a dict.- Drops CLI-only keys and fields that shouldn’t reach GenerateConfig.
- Maps
use_default/force_optionalontoapply_default_values_for_required_fieldsandforce_optional_for_required_fields.- Overwrites
extra_template_data,aliases,custom_formatters_kwargs,output,command_line, andsettings_pathwith already-validated values.- Returns a
GenerateConfigviamodel_validate.This is the right abstraction point and matches the tests’ expectations. Only tiny nit: the
# noqa: PLR0913on the signature may be unnecessary if that rule isn’t enabled, but it’s harmless.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
pyproject.tomlsrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/config.pytests/main/test_main_general.pytests/main/test_public_api_direct.pytests/main/test_public_api_signature_baseline.py
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-25T09:22:14.661Z
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:14.661Z
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.
Applied to files:
src/datamodel_code_generator/config.py
📚 Learning: 2025-12-25T09:22:57.664Z
Learnt from: koxudaxi
Repo: koxudaxi/datamodel-code-generator PR: 2799
File: src/datamodel_code_generator/util.py:49-66
Timestamp: 2025-12-25T09:22:57.664Z
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.
Applied to files:
src/datamodel_code_generator/config.py
🧬 Code graph analysis (4)
tests/main/test_main_general.py (3)
src/datamodel_code_generator/config.py (7)
GenerateConfig(85-217)ParseConfig(571-604)ParserConfig(390-568)Config(92-96)Config(227-231)Config(397-401)Config(578-582)src/datamodel_code_generator/_types/generate_config_dict.py (1)
GenerateConfig(49-169)src/datamodel_code_generator/_types/parser_config_dict.py (1)
ParserConfig(41-151)
src/datamodel_code_generator/config.py (6)
src/datamodel_code_generator/_types/cli_config_dict.py (2)
DataclassArguments(35-45)CliConfigSchema(51-174)src/datamodel_code_generator/_types/generate_config_dict.py (2)
DataclassArguments(36-46)GenerateConfig(49-169)src/datamodel_code_generator/parser/__init__.py (2)
DefaultPutDict(28-47)LiteralType(20-25)src/datamodel_code_generator/util.py (1)
is_pydantic_v2(52-57)src/datamodel_code_generator/model/__init__.py (1)
DataModelSet(25-35)src/datamodel_code_generator/_types/parse_config_dict.py (1)
ParseConfig(17-24)
src/datamodel_code_generator/__main__.py (2)
src/datamodel_code_generator/config.py (6)
GenerateConfig(85-217)Config(92-96)Config(227-231)Config(397-401)Config(578-582)_rebuild_config_models(610-645)src/datamodel_code_generator/util.py (2)
model_dump(254-258)model_validate(261-265)
tests/main/test_public_api_signature_baseline.py (1)
src/datamodel_code_generator/config.py (2)
GenerateConfig(85-217)ParserConfig(390-568)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/config.py
358-358: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
369-369: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
613-613: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
614-614: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
616-616: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
617-617: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
620-620: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__main__.py
42-42: Unused noqa directive (non-enabled: TC003)
Remove unused noqa directive
(RUF100)
175-175: Unused noqa directive (non-enabled: N805)
Remove unused noqa directive
(RUF100)
500-500: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
501-501: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
503-503: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
504-504: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
505-505: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
587-587: Unused noqa directive (non-enabled: PLR0913)
Remove unused noqa directive
(RUF100)
727-727: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
729-729: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
748-748: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
750-750: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
751-751: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1022-1022: Unused noqa directive (non-enabled: PLC0415)
Remove unused noqa directive
(RUF100)
1029-1029: Unused noqa directive (non-enabled: T201)
Remove unused noqa directive
(RUF100)
1132-1132: Unused noqa directive (non-enabled: T201)
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: py312-isort6 on Ubuntu
- GitHub Check: py312-pydantic1 on Ubuntu
- GitHub Check: py312-black23 on Ubuntu
- GitHub Check: 3.12 on macOS
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.10 on Ubuntu
- GitHub Check: 3.14 on Windows
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.13 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (34)
pyproject.toml (1)
247-307: Coverage omit entries and profiles look consistent with new config typesThe additional
run.omitpatterns for_typesmodules and the four newtool.datamodel-codegen.profiles.*sections (generate/parser/parse/cli config dicts) reference existing classes and enums and match the refactored config layout. No issues spotted here.tests/main/test_main_general.py (8)
5-7: New imports are minimal and appropriately scoped
ioandjsonare only used in the new config/CLI validation tests and keep dependencies light. Nothing to change.
27-32: Direct imports of config and parser classes align with public APIImporting
GenerateConfig,ParseConfig,ParserConfig, and the parser classes matches the new config-driven public surface and keeps tests close to the intended usage. Looks good.
108-132: Config file-field validators are well coveredThe tests for
extra_template_datahandling (None, dict, text IO, invalid path) correctly exerciseConfig.validate_file. They assert both successful coercions and failure on non-files, which is exactly what the validator does. No issues.
134-173: CLI rejection tests for invalid JSON-like inputs are preciseThe three tests around invalid
extra_template_data,aliases, andcustom_formatters_kwargsfiles correctly simulate bad structures and assertExit.ERROR. These align with the new error-printing paths in__main__.pyand should prevent silent failures. No problems seen.
200-221: generate(): mutual-exclusivity and mapping support are validated
test_generate_rejects_config_and_optionsasserts the ValueError when mixingconfigand individual options.test_generate_accepts_config_mappingchecks a plain mappingconfigpath returnsNone(since an output file is given).Both match the intended API and will catch regressions in argument handling.
223-250: Base Parser config handling tests are robustThe
DummyParsertests verify:
- Raising when
configand extra options are mixed.- Accepting both
ParserConfiginstances and config mappings.
This mirrors the intended constructor contract and usesparse_raw()as a no-op to exercise the path. Looks correct.
252-265: ParseConfig usage in Parser.parse() is correctly constrainedThe tests ensure
parse(config=ParseConfig(), with_import=True)raises and that a plain mapping forconfigis accepted and returns a truthy result. This matches the new parse signature semantics.
267-325: Per-parser config mixing tests cover key subclassesThe GraphQL, JsonSchema, and OpenAPI parser tests consistently:
- Reject
config+ options combinations.- Accept config mappings and assert a representative attribute (e.g.,
use_standard_collections,base_path,open_api_scopes) is initialized.This gives good coverage of the subclass constructors and their config wiring.
tests/main/test_public_api_direct.py (5)
9-22: Imports and fixtures reflect the intended public APIThis module correctly imports
GenerateConfig,ParserConfig, parser classes, and expected/fixture paths, aligning the tests with the documented public surface rather than internal helpers. Good baseline for API stability.
27-56: GENERATE_CASES comprehensively exercise main input typesThe three generate cases (JSON Schema, OpenAPI, GraphQL) use realistic options and expected outputs. Using
extra_fields="forbid"for OpenAPI is in line with existing behavior. This table-driven approach looks solid.
59-91: PARSER_CASES mirror generate cases and use appropriate optionsThe parser cases pass only parser-relevant options (
use_standard_collections,use_union_operator,extra_fields) and pair them with expected generated files. This keeps the publicParserAPI coverage in sync with generate() coverage.
94-111: generate() public API test correctly switches between config and kwargsThe
use_configflag toggles between constructingGenerateConfig(**options)and passing**optionsdirectly, then normalizes trailing newlines before comparing withassert_output. This is a concise but effective regression test for the newconfigparameter.
113-153: Parser public API test handles headers and forward-ref noise cleanlyThe parser test:
- Exercises both
ParserConfigobjects and kwargs.- Strips the autogenerated header region.
- Normalizes line endings.
- Removes trailing
.update_forward_refs()calls via_strip_update_forward_refs.This avoids brittle comparisons while still asserting semantic equivalence to golden files. Well structured.
tests/main/test_public_api_signature_baseline.py (1)
8-37: Baselines accurately document the new config-driven signatures
_baseline_generateand_BaselineParser.__init__now capture the intended public signatures (configplus**options: Unpack[...]), and the tests compare both keyword-only parameter sets and annotations against the real APIs. This is a good guardrail against future breaking changes.src/datamodel_code_generator/config.py (6)
40-57: TYPE_CHECKING branches and fallbacks look safeThe TYPE_CHECKING vs runtime sections correctly:
- Import precise types when type checking.
- Fall back to
Anyfor Path/ParseResult/DataModel/etc. under Pydantic v1 to avoid import cycles.- Treat
UnionModeasAnyat runtime when not available.This balances type safety with cyclic-import resilience.
Please ensure your current Pydantic v1/v2 matrix still type-checks with these aliases (e.g. run pyright/mypy) to catch any missed forward refs.
76-83: TypedDict alias wiring matches generated typesThe aliases
GenerateConfigDict,ParseConfigDict, andParserConfigDictcorrectly refer to the generated_typesmodules, keeping Pydantic models and the TypedDict schemas in sync. This is important for theUnpack[...]signatures used elsewhere.
85-217: GenerateConfig model mirrors existing CLI/generate optionsThe
GenerateConfigfields align with the options exposed in the CLI and TypedDict definitions, and the Pydantic v1/v2 configuration (extra="forbid", arbitrary_types_allowed=True) is consistent. No obvious mismatches or missing flags based on the provided_typessnippets.Given the size of this model, it’s worth running your existing config-serialization tests (and the new dict-generation profiles) to confirm all fields round-trip correctly between CLI, GenerateConfig, and the generated
GenerateConfigDict.
220-356: CliConfigSchema cleanly separates CLI-only concerns from core GenerateConfig
CliConfigSchemadeliberately includes CLI-only flags (check/debug/watch/etc.) while reusing the same shapes asGenerateConfigfor shared options. Using aField(default_factory=...)foropenapi_scopesis a good choice to avoid mutable-default pitfalls. The v1/v2 config handling mirrorsGenerateConfigand looks consistent.
390-568: ParserConfig._from_generate_config correctly derives parser settingsKey aspects look right:
- Derives
effective_dataclass_argumentsfromGenerateConfig.dataclass_argumentsplusfrozen_dataclasses/keyword_only.- Forces
enum_field_as_literal = LiteralType.Allwhen outputting TypedDicts.- Forces
set_default_enum_member=Truefor dataclasses output.- Uses
model_dumpwith field-set intersection and then enriches via_build_parser_config_overrides.- Validates via
model_validatewith a filtered dict keyed by actual parser fields.This should keep parser behavior in sync with generate() while retaining Pydantic v1/v2 compatibility.
It would be good to run a few end-to-end tests that compare ParserConfig produced via
_from_generate_configwith manually constructed ParserConfig objects, to ensure no important fields are omitted from the intersection logic.
571-604: ParseConfig and its conversion helper are minimal and focused
ParseConfigonly tracks flags relevant toParser.parse(), and_from_generate_configuses the same intersection pattern as ParserConfig. This keeps the parse-time config surface intentionally small and driven byGenerateConfig.src/datamodel_code_generator/__main__.py (13)
42-50: New typing/pydantic imports are appropriateImporting
Mapping,Sequence,BaseModel,Field, andValidationErrorhere is justified by the newConfigmodel and error handling paths. No redundancy or obvious overreach.
143-188: Config.validate_file provides flexible, well-bounded coercionThe
validate_filevalidator:
- Accepts
None,dict, text IO, and string/Path-like values.- Loads JSON via
json.load/json.loadsand raisesErrorwhen the path is not a file, matching the new tests.
One minor nuance:Path(value)will accept non-strvalue(e.g.Pathitself) but that’s OK sinceisinstance(value, dict)/TextIOBaseare checked first. This is fine.
255-309: Pre-validators for CLI string options are straightforward and compatibleThe
model_validator(mode="before")methods to split comma-separatedadditional_imports,custom_formatters, parse JSON forduplicate_name_suffix, migrateparent_scoped_naming, and normalizeclass_decoratorskeep CLI convenience while feeding structured data into the underlying config. Error messages (e.g., invalid JSON string) are clear.
330-442: Output/time/naming/all-exports validators mirror existing behaviorThe v2 vs v1 branches of validators enforce:
output_datetime_classconstraints for dataclasses.original_field_name_delimiterrequiringsnake_case_field.- mutual exclusivity for custom file header options.
keyword_onlyvs target Python version.use_annotatedimplyingfield_constraints.all_exports_collision_strategyrequiring recursive scope.These behaviors are consistent with the rest of the codebase and the tests in
test_main_general.py.
443-565: Config inherits GenerateConfig cleanly while adding CLI-only surfaceThe dataclass-style field definitions on
Configmatch or specialize those inGenerateConfig:
- Shared fields keep compatible types (often narrowed to Optional[...] for CLI parsing).
- CLI-only fields (input/input_model/check/debug/watch/etc.) remain local to
Configand are later stripped into_generate_config.Using Mapping/Sequence for
aliases/strict_typesis consistent with how validators treat them. Looks correct.
567-585: merge_args correctly merges namespace into Config with validationThe method:
- Collects only attributes present on
argsand notNone.- Applies two derived flags (
use_annotated→field_constraints) later in main, not here.- Re-parses via
Config.parse_objto re-run validators, then assigns validated values.This keeps CLI parsing robust and leverages Pydantic validation without duplicating logic.
630-641: _extract_additional_imports mutates template data by designThe helper both:
- Extracts and normalizes
additional_importsand- Pops them out of the
extra_template_dataentries.Given it’s only called after a copy (
defaultdict(dict, **config.extra_template_data)), this is safe and keeps template data clean for later rendering. Behavior matches new tests.
700-761: _load_model_schema’s config-model rebuild and Pydantic v2 handling are solidEnhancements here:
- Optionally calls a module-level
_rebuild_config_models()if present, allowing imported config modules to resolve forward refs lazily.- Suppresses noisy
PydanticJsonSchemaWarningwhen callingmodel_json_schema()orTypeAdapter(...).json_schema()with warnings filters.The rest of the function’s error messages are explicit and user-friendly. No functional issues spotted.
Please run the new
--input-modelpaths against both dict and Pydantic model targets in your test matrix to confirm_rebuild_config_models()behaves as expected when importing config modules.
764-804: pyproject profile merging is correct and supports profiles gracefully
_get_pyproject_toml_config:
- Walks upwards to find the nearest
pyproject.toml.- Merges a named
profileover the base[tool.datamodel-codegen]config.- Produces CLI/Config-friendly keys by replacing
-with_.- Provides clear errors when profile is missing or pyproject absent.
This underpins the new TypedDict-generation profiles and looks good.
940-960: run_generate_from_config correctly funnels through GenerateConfigThe wrapper:
- Calls
config.to_generate_config(...)with validated mappings and paths.- Passes
config=generate_configintogenerate()instead of individual options.- Still respects
outputhandling via the returnedGenerateConfig.This keeps the main function from duplicating config-mapping logic and is consistent with new tests rejecting mixed config/options usage.
1021-1031: Config parsing now handles both Error and ValidationError uniformlyWrapping parsing and
_rebuild_config_models()in a try/except that catches bothErrorandValidationErrorand prints a single string message gives clearer feedback when pyproject/CLI config fails validation. This matches the new tests around invalid values.
1125-1171: Improved validation and error messages for template/alias/formatter mappingsThe new blocks:
- Wrap
extra_template_datadefaultdictcoercion in a try/except and print a clear message on structural errors.- Ensure
aliasesandcustom_formatters_kwargsare dicts with string keys/values before proceeding, with explicit stderr messages when invalid.These changes directly address prior review feedback and are well covered by tests in
test_main_general.py.
1186-1205: run_generate_from_config integration respects new mappingsThe call to
run_generate_from_confignow passes:
extra_template_data(possibly None or adefaultdict),aliases,custom_formatters_kwargs,settings_path=config.output.This keeps all derived mappings flowing through the same translation layer. Using
settings_path=config.outputmakes sense given formatter/Black/ruff should honor the output location’s pyproject.
|
|
||
| def test_main_aliases_with_pydantic_v1_config(tmp_path: Path) -> None: | ||
| """Exercise pydantic v1 config branches for coverage.""" | ||
| import datamodel_code_generator.config as config_module |
Check notice
Code scanning / CodeQL
Module is imported with 'import' and 'import from' Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, to fix this issue you should avoid importing the same module with both import xxx and from xxx import yyy. Keep the from ... import ... form (as recommended) and, where you need module-style access, bind the module object via that existing import, e.g. import package as _pkg; module = _pkg.module or similar, or import the module directly from the package that is already imported.
In this specific case, we already import from the top of the file:
from datamodel_code_generator.config import GenerateConfig, ParseConfig, ParserConfigbut inside test_main_aliases_with_pydantic_v1_config we do:
import datamodel_code_generator.config as config_module
from datamodel_code_generator import utilThe fix is to remove the inner import datamodel_code_generator.config as config_module and instead import the top-level datamodel_code_generator package once at the module level so that we can refer to datamodel_code_generator.config in the test. That preserves behavior while avoiding the duplicate style of importing the same submodule. Concretely:
- At the top of
tests/main/test_main_general.py, addimport datamodel_code_generator. - In
test_main_aliases_with_pydantic_v1_config, remove theimport datamodel_code_generator.config as config_moduleline. - Replace uses of
config_modulein that test withdatamodel_code_generator.config.
No additional methods or definitions are required; only imports and name references change.
| @@ -11,6 +11,7 @@ | ||
| import pytest | ||
| from inline_snapshot import snapshot | ||
|
|
||
| import datamodel_code_generator | ||
| from datamodel_code_generator import ( | ||
| AllExportsScope, | ||
| DataModelType, | ||
| @@ -164,13 +165,12 @@ | ||
|
|
||
| def test_main_aliases_with_pydantic_v1_config(tmp_path: Path) -> None: | ||
| """Exercise pydantic v1 config branches for coverage.""" | ||
| import datamodel_code_generator.config as config_module | ||
| from datamodel_code_generator import util | ||
|
|
||
| if util.is_pydantic_v2(): | ||
| pytest.skip("pydantic v1-only coverage") | ||
| assert config_module.Path is config_module.Any | ||
| config_module._rebuild_config_models() | ||
| assert datamodel_code_generator.config.Path is datamodel_code_generator.config.Any | ||
| datamodel_code_generator.config._rebuild_config_models() | ||
| run_main_and_assert( | ||
| input_path=JSON_SCHEMA_DATA_PATH / "person.json", | ||
| output_path=tmp_path / "out.py", |
|
📢 Related PR Released: 0.51.0 PR #2832, which references this PR, has been released. See the release notes for details. |
Summary by CodeRabbit
New Features
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.