Add --no-treat-dot-as-module option for flat output structure#2732
Add --no-treat-dot-as-module option for flat output structure#2732
Conversation
|
Warning Rate limit exceeded@koxudaxi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 47 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (21)
WalkthroughThe pull request converts the Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~35 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🤖 Generated by GitHub Actions
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2732 +/- ##
=======================================
Coverage 99.36% 99.36%
=======================================
Files 83 83
Lines 12068 12081 +13
Branches 1456 1456
=======================================
+ Hits 11991 12004 +13
Misses 45 45
Partials 32 32
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:
|
CodSpeed Performance ReportMerging #2732 will not alter performanceComparing Summary
Footnotes
|
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/cli-reference/template-customization.md (1)
263-278: Documentation inconsistency: mismatched flag names.The section is titled
--no-treat-dot-as-module(line 263) and the reference link uses this name (line 277), but:
- Line 267 references the old flag name: "The
--treat-dot-as-moduleflag"- Line 274 shows usage with the old flag:
--treat-dot-as-moduleThese should be updated to consistently use
--no-treat-dot-as-modulethroughout the section.🔎 Proposed fix
-The `--treat-dot-as-module` flag configures the code generation behavior. +The `--no-treat-dot-as-module` flag configures the code generation behavior. !!! tip "Usage" ```bash - datamodel-codegen --input schema.json --treat-dot-as-module # (1)! + datamodel-codegen --input schema.json --no-treat-dot-as-module # (1)! ```src/datamodel_code_generator/types.py (1)
843-856: Inconsistent use oftreat_dot_as_moduleparameter in dynamic model creation.On line 843, you correctly coerce
NonetoFalse:self.treat_dot_as_module: bool = treat_dot_as_module or FalseHowever, on line 852, you pass the raw
treat_dot_as_moduleparameter (which could still beNone) tocreate_model:treat_dot_as_module=(bool, treat_dot_as_module),When
treat_dot_as_moduleisNone, this results increate_modelreceiving(bool, None)for a non-optional bool field, which could cause unexpected behavior or validation issues.🔎 Proposed fix
self.data_type: type[DataType] = create_model( "ContextDataType", python_version=(PythonVersion, python_version), use_standard_collections=(bool, use_standard_collections), use_generic_container=(bool, use_generic_container_types), use_union_operator=(bool, use_union_operator), - treat_dot_as_module=(bool, treat_dot_as_module), + treat_dot_as_module=(bool, self.treat_dot_as_module), use_serialize_as_any=(bool, use_serialize_as_any), __base__=DataType, )
🧹 Nitpick comments (12)
src/datamodel_code_generator/model/dataclass.py (1)
221-221: Clean up unusednoqadirective.The
noqa: FBT001directive on line 221 is no longer needed since the parameter type changed frombooltobool | None, which already addresses the boolean-trap concern that FBT001 warns about.🔎 Proposed fix
- treat_dot_as_module: bool | None = None, # noqa: FBT001 + treat_dot_as_module: bool | None = None,Based on static analysis hints.
src/datamodel_code_generator/__main__.py (1)
454-454: Consider using consistent type annotation style.This line uses
Optional[bool]while other files in this PR usebool | None(e.g., dataclass.py line 65, base_model.py lines 291 and 348). While both are valid, the inconsistency is notable.Since other fields in this Config class also use
Optional[...]style, keepingOptional[bool]maintains local consistency. However, you could update thenoqacomment or remove it if you decide to standardize on one style across the codebase.Based on static analysis hints.
src/datamodel_code_generator/model/pydantic/types.py (1)
184-184: Remove unusednoqadirective.The
# noqa: FBT001comment is flagged as unused because the FBT001 rule is not enabled in your Ruff configuration.🔎 Proposed fix
- treat_dot_as_module: bool | None = None, # noqa: FBT001 + treat_dot_as_module: bool | None = None,src/datamodel_code_generator/types.py (1)
828-828: Remove unusednoqadirective.The
# noqa: FBT001comment is flagged as unused because the FBT001 rule is not enabled in your Ruff configuration.🔎 Proposed fix
- treat_dot_as_module: bool | None = None, # noqa: FBT001 + treat_dot_as_module: bool | None = None,src/datamodel_code_generator/model/types.py (1)
87-87: Remove unusednoqadirective.The
# noqa: FBT001comment is flagged as unused because the FBT001 rule is not enabled in your Ruff configuration.🔎 Proposed fix
- treat_dot_as_module: bool | None = None, # noqa: FBT001 + treat_dot_as_module: bool | None = None,src/datamodel_code_generator/model/pydantic_v2/types.py (1)
72-99: Tri-statetreat_dot_as_modulelooks good; drop unusednoqaThe change to
treat_dot_as_module: bool | None = Noneand its propagation intosuper().__init__andcreate_model(...)is consistent with the new tri-state behavior and doesn’t introduce obvious correctness issues.Ruff is right that
# noqa: FBT001is now unused; you can safely remove it to keep lint clean.Proposed lint-only cleanup
- treat_dot_as_module: bool | None = None, # noqa: FBT001 + treat_dot_as_module: bool | None = None,src/datamodel_code_generator/reference.py (1)
499-555: Tri-state dotted-name handling is sound; remove unusednoqaThe new logic in
get_class_name:
- Uses
self.treat_dot_as_module is not Falseso thatNoneandTrueboth keep dotted module prefixes, while an explicitFalseflattens dots.- Replaces
"."with"_"when modularization is disabled, ensuring resulting names stay valid and avoiding hidden dotted paths in the non-modular case.This matches the intended
--no-treat-dot-as-modulebehavior and keepsReference.short_nameconsistent (no dots when flattening).Ruff’s
RUF100note about# noqa: FBT001on the constructor parameter is valid; that directive can be dropped.Proposed lint-only cleanup
- parent_scoped_naming: bool = False, # noqa: FBT001, FBT002 - treat_dot_as_module: bool | None = None, # noqa: FBT001 + parent_scoped_naming: bool = False, # noqa: FBT001, FBT002 + treat_dot_as_module: bool | None = None,Also applies to: 848-883
tests/parser/test_openapi.py (1)
456-466: Tests correctly opt into modular output; consider flat-mode coverageUsing
treat_dot_as_module=Truein the alias and modular tests is a good way to lock in the modular output behavior now that the flag is tri-state.You might optionally add a small companion test with
treat_dot_as_module=False(or via the CLI flag that maps to it) to assert the new “flat output structure” behavior end-to-end, but it isn’t strictly required for this change set.Also applies to: 468-477
tests/model/test_base.py (1)
302-353: Tests correctly capture newtreat_dot_as_modulesemantics; consider adding aNonecaseThe updated expectations for
TruevsFalse(with and withoutfile_path) match the newget_module_pathbehavior. You may optionally add a small test fortreat_dot_as_module=Noneto lock in the “backward compatible” default semantics described in the helper’s docstring.src/datamodel_code_generator/model/pydantic_v2/base_model.py (1)
188-220: Tri-statetreat_dot_as_moduleis correctly threaded; clean up unusednoqaThe new
treat_dot_as_module: bool | None = Noneparameter is passed cleanly into the base DataModel both in__init__andcreate_base_class_model, so Pydantic v2 models inherit the same behavior as the rest of the stack.Ruff reports that the
# noqa: FBT001on thetreat_dot_as_moduleargument (Line 288) is unused. You can drop that directive without changing behavior.Also applies to: 281-309
src/datamodel_code_generator/model/msgspec.py (1)
127-161: msgspec Struct and DataTypeManager correctly propagatetreat_dot_as_module; remove unusednoqaThe added
treat_dot_as_module: bool | None = Noneparameters inStruct.__init__,Struct.create_base_class_model, andDataTypeManager.__init__are passed through consistently to the DataModel/type-manager base, matching the new tri-state design.Ruff flags the
# noqa: FBT001directives on these new parameters (Lines 177 and 507) as unused. They’re safe to delete for a cleaner lint profile.Also applies to: 170-193, 496-523
src/datamodel_code_generator/model/base.py (1)
500-578: DataModel tri-state propagation is sound; drop unusednoqaoncreate_base_class_modelStoring
treat_dot_as_moduleon_treat_dot_as_moduleand feeding it into:
create_reuse_model(...)module_path/module_name(via the helper functions)create_base_class_model(through subclass overrides)ensures that all DataModel instances—original, reused, and generic base—share consistent module naming behavior.
Ruff notes that the
# noqa: FBT001on thetreat_dot_as_moduleparameter increate_base_class_model(Line 737) is unused; you can remove it safely.Also applies to: 610-624, 709-717, 731-738
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (31)
docs/cli-reference/index.mddocs/cli-reference/quick-reference.mddocs/cli-reference/template-customization.mdsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/arguments.pysrc/datamodel_code_generator/cli_options.pysrc/datamodel_code_generator/model/base.pysrc/datamodel_code_generator/model/dataclass.pysrc/datamodel_code_generator/model/enum.pysrc/datamodel_code_generator/model/msgspec.pysrc/datamodel_code_generator/model/pydantic/base_model.pysrc/datamodel_code_generator/model/pydantic/types.pysrc/datamodel_code_generator/model/pydantic_v2/base_model.pysrc/datamodel_code_generator/model/pydantic_v2/types.pysrc/datamodel_code_generator/model/scalar.pysrc/datamodel_code_generator/model/typed_dict.pysrc/datamodel_code_generator/model/types.pysrc/datamodel_code_generator/model/union.pysrc/datamodel_code_generator/parser/base.pysrc/datamodel_code_generator/parser/graphql.pysrc/datamodel_code_generator/parser/jsonschema.pysrc/datamodel_code_generator/parser/openapi.pysrc/datamodel_code_generator/reference.pysrc/datamodel_code_generator/types.pytests/data/expected/parser/openapi/openapi_parser_parse_alias/fo_o/__init__.pytests/data/expected/parser/openapi/openapi_parser_parse_modular/foo/__init__.pytests/data/expected/parser/openapi/openapi_parser_parse_modular/nested/__init__.pytests/data/expected/parser/openapi/openapi_parser_parse_modular/woo/__init__.pytests/model/test_base.pytests/parser/test_openapi.py
💤 Files with no reviewable changes (1)
- tests/data/expected/parser/openapi/openapi_parser_parse_alias/fo_o/init.py
🧰 Additional context used
🧬 Code graph analysis (6)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/woo/__init__.py (7)
tests/data/expected/parser/openapi/openapi_parser_parse_additional_properties/with_import_format.py (3)
Error(39-44)Id(31-32)Result(51-52)tests/data/expected/parser/openapi/openapi_parser_parse/with_import.py (3)
Error(34-36)Id(26-27)Result(54-55)tests/data/expected/main_kr/main/output.py (3)
Error(38-40)Id(30-31)Result(66-67)tests/data/expected/parser/openapi/openapi_parser_parse/with_import_format.py (3)
Error(36-38)Id(28-29)Result(56-57)tests/data/expected/parser/openapi/openapi_parser_parse_alias/__init__.py (4)
Error(17-19)Id(35-36)Result(39-40)Source(43-44)tests/data/expected/parser/openapi/openapi_parser_parse_modular/_internal.py (1)
OptionalModel(10-11)src/datamodel_code_generator/parser/base.py (2)
Result(646-651)Source(654-666)
tests/model/test_base.py (1)
src/datamodel_code_generator/model/base.py (1)
get_module_path(422-440)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/nested/__init__.py (3)
src/datamodel_code_generator/__init__.py (1)
Error(312-321)tests/data/expected/parser/openapi/openapi_parser_parse_modular/_internal.py (1)
OptionalModel(10-11)src/datamodel_code_generator/parser/base.py (2)
Result(646-651)Source(654-666)
src/datamodel_code_generator/reference.py (1)
src/datamodel_code_generator/model/base.py (3)
name(671-673)class_name(692-694)class_name(697-701)
tests/parser/test_openapi.py (1)
src/datamodel_code_generator/parser/openapi.py (1)
OpenAPIParser(175-914)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/foo/__init__.py (1)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/_internal.py (1)
OptionalModel(10-11)
🪛 Ruff (0.14.8)
src/datamodel_code_generator/model/types.py
87-87: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/pydantic_v2/types.py
83-83: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/pydantic_v2/base_model.py
288-288: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/pydantic/types.py
184-184: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/dataclass.py
221-221: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/reference.py
518-518: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/types.py
828-828: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/__main__.py
454-454: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/msgspec.py
177-177: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
507-507: Unused noqa directive (non-enabled: FBT001)
Remove unused noqa directive
(RUF100)
src/datamodel_code_generator/model/base.py
737-737: Unused noqa directive (non-enabled: FBT001)
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). (1)
- GitHub Check: benchmarks
🔇 Additional comments (19)
src/datamodel_code_generator/model/pydantic/base_model.py (1)
291-291: LGTM!The parameter type changes are consistent with the broader refactoring to make
treat_dot_as_moduleoptional across the codebase.Also applies to: 348-348
src/datamodel_code_generator/model/scalar.py (1)
60-60: LGTM!The parameter type change is consistent with the broader refactoring.
src/datamodel_code_generator/model/enum.py (1)
64-64: LGTM!The parameter type change is consistent with the broader refactoring.
docs/cli-reference/quick-reference.md (1)
121-121: LGTM!Documentation updates correctly reflect the new
--no-treat-dot-as-moduleflag naming.Also applies to: 226-226
src/datamodel_code_generator/parser/openapi.py (1)
264-264: LGTM!The parameter type change is consistent with the broader refactoring to support optional
treat_dot_as_modulebehavior.docs/cli-reference/index.md (1)
114-114: LGTM!The documentation correctly reflects the new
--no-treat-dot-as-moduleCLI option and is properly placed in the alphabetical index.src/datamodel_code_generator/__init__.py (1)
467-467: LGTM!The parameter type change from
booltobool | Nonecorrectly enables the optional/unspecified state for thetreat_dot_as_moduleparameter in the public API.tests/data/expected/parser/openapi/openapi_parser_parse_modular/woo/__init__.py (1)
1-3: LGTM!The test expected output correctly shows the new modular structure with imports from
._internaland a properly declared__all__for the public API.src/datamodel_code_generator/parser/graphql.py (1)
180-180: LGTM!The parameter type change from
booltobool | Noneis consistent with the broader refactoring and correctly propagates through the parser initialization chain.tests/data/expected/parser/openapi/openapi_parser_parse_modular/nested/__init__.py (1)
1-3: LGTM!The test expected output correctly shows the new modular structure with imports from
._internaland a properly declared__all__for the public API.src/datamodel_code_generator/cli_options.py (1)
168-181: Canonical CLI option for treat-dot-as-module is consistentDocumenting
--no-treat-dot-as-moduleas the canonical option and registering it inCLI_OPTION_METAfits the canonicalization strategy (longest option string) and should keep the docs/argparse sync logic happy.tests/data/expected/parser/openapi/openapi_parser_parse_modular/foo/__init__.py (1)
1-3: Updated modular exports and__all__look consistentThe re-export from
. _internaland matching__all__list align with the other modular expected packages and should reflect the new naming behavior correctly.src/datamodel_code_generator/model/union.py (1)
29-63: Union base correctly adopts optionaltreat_dot_as_moduleAllowing
treat_dot_as_module: bool | None = Noneand forwarding it intosuper().__init__keeps GraphQL union models consistent with the rest of the model types under the new tri-state behavior.src/datamodel_code_generator/model/typed_dict.py (1)
54-88: TypedDict now participates in tri-statetreat_dot_as_moduleThe widened
treat_dot_as_moduleparameter and its forwarding intosuper().__init__align TypedDict models with the rest of the codegen pipeline’s dotted-name handling.src/datamodel_code_generator/parser/jsonschema.py (1)
511-607: JsonSchemaParser correctly propagates optionaltreat_dot_as_moduleWidening
treat_dot_as_moduletobool | NoneinJsonSchemaParser.__init__and forwarding it tosuper().__init__keeps the JSON Schema pipeline consistent with the new tri-state behavior and allows explicit “flat” vs modular control via the shared infrastructure. The rest of the uses ofself.treat_dot_as_moduleremain coherent with that design.Also applies to: 688-704
src/datamodel_code_generator/arguments.py (1)
267-272: Tri-state CLI flag wiring for--treat-dot-as-modulelooks consistentUsing
BooleanOptionalActionwithdefault=Nonefits the newbool | Nonesemantics and matches other options in this file. The help text clearly explains the positive and negative forms; no issues from this side.src/datamodel_code_generator/model/base.py (1)
409-446: Module naming helpers correctly implement tri-state behaviorThe updated
sanitize_module_name,get_module_path, andget_module_nameencode the documented semantics:
True: preserve dots in sanitized stems and split names on dots.False: sanitize stems (no dots) and avoid name-based splitting.None: split names on dots but sanitize stems (back-compat).This lines up with the new tests in
tests/model/test_base.py.src/datamodel_code_generator/parser/base.py (2)
676-789: Tri-state parameter threading is consistent with DataTypeManager's bool-only design; verify it remains sufficientThe Parser accepts
treat_dot_as_module: bool | None = Noneand correctly threads it:
- To
DataTypeManagercoerced astreat_dot_as_module or False(line 786) → only bool semantics used- To
ModelResolverpreserving tri-state (line 895) → explicitly checksis not False(reference.py:857)- On
selfpreserving tri-state (line 920) → used in parse() truthy check (line 2918)DataTypeManager's
treat_dot_as_module: bool = Falsefield (types.py:337) means it has no need to distinguishNonefromFalse. The coercion viaor Falseis appropriate if this remains true. However, if DataTypeManager's type behavior must someday distinguish the "backward compatible default" (None) from explicitFalse, theor Falsecoercion will need to be removed and the field type changed to accept tri-state.For now, the wiring is sound because DataTypeManager only needs binary semantics while ModelResolver correctly leverages the tri-state information.
2915-2923: Confirm that the truthiness check fortreat_dot_as_modulecorrectly handles the tri-state parameterThe code accepts
treat_dot_as_module: bool | None = Nonebut stores the raw value inself.treat_dot_as_moduleand later checks it withif self.treat_dot_as_module. This truthiness check groupsNonewithFalse, reserving the modular postprocessing only for explicitTrue. While this appears intentional (the parameter acceptsNoneas the default), tests only verifyTrueandFalsecases—theNonecase behavior is undocumented. Verify this matches the intended backward-compatible semantics.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/datamodel_code_generator/__main__.py (1)
371-476: Remove unusednoqaontreat_dot_as_moduleRuff flags
# noqa: UP045on Line 455 as unused. Since this field is correctly typed asOptional[bool]and UP045 isn’t enabled, thenoqais unnecessary noise.You can safely drop the
# noqa: UP045comment.Minimal cleanup
- treat_dot_as_module: Optional[bool] = None # noqa: UP045 + treat_dot_as_module: Optional[bool] = None
🧹 Nitpick comments (4)
src/datamodel_code_generator/parser/base.py (2)
676-773: Check tri-state semantics between Parser, DataTypeManager, and ModelResolverYou now accept
treat_dot_as_module: bool | None = None, but:
DataTypeManageris constructed withtreat_dot_as_module=treat_dot_as_module or False(Line 787), coercingNonetoFalse.ModelResolverstill receives the rawtreat_dot_as_module(Line 896).self.treat_dot_as_moduleis stored as the raw value (Line 922).This means
NoneandFalseare indistinguishable forDataTypeManager, but may differ whereverModelResolveror other components interpretNonespecially.If the intent is that
Nonebehave exactly likeFalseeverywhere, this is fine. If insteadNoneis supposed to mean “auto” or “inherit default” for name/module resolution, you might need to avoid theor Falsecoercion and/or normalize once up-front.Example adjustment if `None` should be preserved
- self.data_type_manager: DataTypeManager = data_type_manager_type( + # If DataTypeManager now understands tri-state semantics, avoid + # coercing None to False here. + self.data_type_manager: DataTypeManager = data_type_manager_type( @@ - target_datetime_class=target_datetime_class, - treat_dot_as_module=treat_dot_as_module or False, + target_datetime_class=target_datetime_class, + treat_dot_as_module=treat_dot_as_module if treat_dot_as_module is not None else False,
2917-2924: Confirm intended default fortreat_dot_as_module=Noneinparse()The final return branches on truthiness:
return ( self.__postprocess_result_modules(results) if self.treat_dot_as_module else { ...flattening logic... } )So
treat_dot_as_modulevaluesFalseandNoneboth take the “flatten” branch. IfNoneis meant to be distinct from an explicitFalse(e.g., to preserve previous default behavior while allowing explicit opt‑out), this code doesn’t differentiate them.Please confirm that “unspecified” (None) is indeed supposed to behave identically to
Falsehere; otherwise you may want to branch explicitly onis True/is False.src/datamodel_code_generator/__main__.py (1)
83-87: Consider addingtreat_dot_as_moduleto BOOLEAN_OPTIONAL_OPTIONSYou’ve migrated
treat_dot_as_moduleto an Optional[bool] flag (BooleanOptionalAction on the CLI), butBOOLEAN_OPTIONAL_OPTIONScurrently only includesuse_specialized_enumanduse_standard_collections. As a result,generate_cli_command()will emit--treat-dot-as-modulefor True but nothing for False, even though--no-treat-dot-as-moduleexists.Adding
treat_dot_as_modulehere would letgenerate_cli_commandround-trip pyproject configs more faithfully.Diff to include `treat_dot_as_module`
-BOOLEAN_OPTIONAL_OPTIONS: frozenset[str] = frozenset({ - "use_specialized_enum", - "use_standard_collections", -}) +BOOLEAN_OPTIONAL_OPTIONS: frozenset[str] = frozenset({ + "use_specialized_enum", + "use_standard_collections", + "treat_dot_as_module", +})src/datamodel_code_generator/arguments.py (1)
274-279: LGTM! CLI argument properly updated for tri-state behavior.The use of
BooleanOptionalActioncorrectly provides both--treat-dot-as-moduleand--no-treat-dot-as-moduleflags with aNonedefault for the unspecified case. The help text clearly explains both behaviors.💡 Optional: Consider clarifying default behavior in help text
The help text explains both flag behaviors but doesn't explicitly state what happens when neither flag is specified (the
Nonedefault). Consider adding a sentence like:"--treat-dot-as-module", help="Treat dotted schema names as module paths, creating nested directory structures (e.g., 'foo.bar.Model' " - "becomes 'foo/bar.py'). Use --no-treat-dot-as-module to keep dots in names as underscores for single-file output.", + "becomes 'foo/bar.py'). Use --no-treat-dot-as-module to keep dots in names as underscores for single-file output. " + "Default behavior (when neither flag is specified) splits names while sanitizing file paths.", action=BooleanOptionalAction, default=None,This is optional and doesn't affect functionality.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
docs/cli-reference/index.mddocs/cli-reference/quick-reference.mdsrc/datamodel_code_generator/__init__.pysrc/datamodel_code_generator/__main__.pysrc/datamodel_code_generator/arguments.pysrc/datamodel_code_generator/cli_options.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/data/expected/main/jsonschema/no_treat_dot_single/__init__.pytests/data/expected/main/jsonschema/no_treat_dot_single/v0_0_39_job.pytests/data/expected/main/jsonschema/treat_dot_as_module_single_no_treat/__init__.pytests/data/expected/main/jsonschema/treat_dot_as_module_single_no_treat/model_schema.pytests/data/expected/main/jsonschema/treat_dot_single/__init__.pytests/data/expected/main/jsonschema/treat_dot_single/v0/0/39/__init__.pytests/data/expected/main/jsonschema/treat_dot_single/v0/0/39/job.pytests/data/expected/main/jsonschema/treat_dot_single/v0/0/__init__.pytests/data/expected/main/jsonschema/treat_dot_single/v0/__init__.pytests/data/jsonschema/no_treat_dot_single/v0.0.39.job.jsontests/main/jsonschema/test_main_jsonschema.pytests/model/test_base.py
✅ Files skipped from review due to trivial changes (7)
- tests/data/expected/main/jsonschema/treat_dot_as_module_single_no_treat/model_schema.py
- tests/data/expected/main/jsonschema/treat_dot_single/v0/0/39/init.py
- tests/data/expected/main/jsonschema/treat_dot_as_module_single_no_treat/init.py
- tests/data/expected/main/jsonschema/treat_dot_single/v0/0/init.py
- tests/data/expected/main/jsonschema/treat_dot_single/init.py
- tests/data/expected/main/jsonschema/no_treat_dot_single/init.py
- tests/data/expected/main/jsonschema/treat_dot_single/v0/init.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/datamodel_code_generator/cli_options.py
- docs/cli-reference/index.md
🧰 Additional context used
🧬 Code graph analysis (2)
tests/data/expected/main/jsonschema/no_treat_dot_single/v0_0_39_job.py (2)
tests/data/expected/main/jsonschema/treat_dot_single/v0/0/39/job.py (1)
Job(10-12)src/datamodel_code_generator/model/base.py (1)
name(671-673)
tests/model/test_base.py (1)
src/datamodel_code_generator/model/base.py (1)
get_module_path(422-440)
🪛 Ruff (0.14.8)
src/datamodel_code_generator/__main__.py
455-455: Unused noqa directive (non-enabled: UP045)
Remove unused noqa directive
(RUF100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: 3.12 on Windows
- GitHub Check: 3.11 on Windows
- GitHub Check: py312-isort5 on Ubuntu
- GitHub Check: py312-isort7 on Ubuntu
- GitHub Check: py312-black22 on Ubuntu
- GitHub Check: 3.10 on Windows
- GitHub Check: 3.14 on Ubuntu
- GitHub Check: benchmarks
- GitHub Check: Analyze (python)
🔇 Additional comments (17)
tests/data/jsonschema/no_treat_dot_single/v0.0.39.job.json (1)
1-14: LGTM!The JSON Schema is well-structured and serves as an appropriate test fixture for the new
--no-treat-dot-as-moduleoption. The filename with version-style dots (v0.0.39.job.json) directly addresses the issue described in #1535, ensuring that versioned schema names won't be incorrectly split into nested module paths.tests/data/expected/main/jsonschema/treat_dot_single/v0/0/39/job.py (1)
1-12: LGTM! Clean generated code structure.The generated Pydantic model is correct and follows best practices. The file demonstrates the expected output format when dots in schema names are treated as module separators (creating the v0/0/39/ directory structure from the original "v0.0.39.job.json" schema name). As a test fixture, this properly validates the generation behavior.
tests/data/expected/main/jsonschema/no_treat_dot_single/v0_0_39_job.py (1)
1-12: Expected output file matches new no-treat-dot behaviorThe model structure and filename (
v0_0_39_job.py) correctly reflect the flat, no-dot-as-module layout; nothing to change here.src/datamodel_code_generator/parser/openapi.py (2)
180-280: OpenAPIParser tri-statetreat_dot_as_modulewiring is consistentChanging the ctor parameter to
bool | None = Noneand forwarding it unchanged intosuper().__init__keeps behavior aligned with the baseParserwhile allowing the new tri‑state. No issues spotted here.
647-759: Passingself.treat_dot_as_moduleinto_create_data_modelis appropriatePropagating the parser-level
treat_dot_as_modulevalue into parameter models ensures consistent handling between operation-parameter models and other generated models. This looks correct.src/datamodel_code_generator/parser/graphql.py (2)
97-196: GraphQLParsertreat_dot_as_modulepropagation is consistent with ParserThe ctor now takes
treat_dot_as_module: bool | None = Noneand forwards it tosuper().__init__, matching the base Parser’s signature and behavior. No issues found.
582-621: Passingtreat_dot_as_moduleinto_create_data_modelfor GraphQL objectsIncluding
treat_dot_as_module=self.treat_dot_as_modulewhen creating object-like models keeps GraphQL behavior aligned with JSON/OpenAPI models. Looks correct.src/datamodel_code_generator/__main__.py (1)
668-781: Config → generate() wiring for tri-statetreat_dot_as_modulelooks correct
Config.treat_dot_as_module: Optional[bool]is passed throughrun_generate_from_config()intogenerate(..., treat_dot_as_module=config.treat_dot_as_module, ...), matching the updated public API. No behavioral issues seen here.src/datamodel_code_generator/__init__.py (2)
382-488: Publicgenerate()API updated cleanly to Optional[bool]The
generate()signature now acceptstreat_dot_as_module: bool | None = None, and forwards this directly into the selected parser ctor. This keeps the public API aligned with Parser/OpenAPIParser/GraphQLParser without breaking existing callers that passTrue/False. Looks good.
633-734: Parser construction correctly forwardstreat_dot_as_moduleWithin
generate(), theparser_class(...)call passestreat_dot_as_module=treat_dot_as_module, ensuring the tri‑state flag from CLI/Config reaches the parser layer. No additional changes needed here.src/datamodel_code_generator/parser/jsonschema.py (1)
594-594: LGTM! Parameter signature updated correctly for tri-state behavior.The change from
bool = Falsetobool | None = Noneproperly supports the new tri-state flag behavior (True/False/None) introduced by the--no-treat-dot-as-moduleoption. The parameter is correctly forwarded to the parent class.tests/model/test_base.py (3)
306-306: LGTM! Test expectation correctly updated for flat output mode.When
treat_dot_as_module=False, the new behavior correctly:
- Sanitizes the file stem by replacing dots with underscores (
array_commons_schema)- Omits the name-based module hierarchy (no
array-commonscomponent)This aligns with the flat output structure goal of the
--no-treat-dot-as-moduleoption.
316-327: LGTM! Explicit tests improve clarity for tri-state behavior.Splitting the combined test into two explicit cases makes the behavioral difference clear:
treat_dot_as_module=True: Splits dotted names into module hierarchy["my_module"]treat_dot_as_module=False: Returns empty list[](flat structure, no hierarchy)Both expectations correctly match the implementation logic.
336-338: LGTM! Parametrized test expectations correctly updated.The False cases now consistently expect empty lists
[], matching the flat output behavior where dotted names are not split into module hierarchies.tests/main/jsonschema/test_main_jsonschema.py (3)
356-372: LGTM! Excellent parameterization for tri-state behavior.The refactored test properly covers all three states of the
treat_dot_as_moduleparameter:
- Explicit enable with
--treat-dot-as-module- Default/unspecified (None)
- Explicit disable with
--no-treat-dot-as-moduleBoth the default and explicit disable correctly map to the same expected output (
"treat_dot_not_as_module"), which aligns with the PR objective of providing an explicit flag to disable dot-splitting behavior.
393-409: LGTM! Comprehensive test for the new flag.This test properly validates the
--no-treat-dot-as-moduleflag in single-file mode, addressing the core issue from #1535. The CLI documentation marker ensures this important option is properly documented for users who need to preserve dotted names (like versioned schemas) without splitting them into modules.
412-429: LGTM! Excellent coverage for version-style schema names.This test directly addresses the motivating use case from issue #1535 (versioned schema names like "v0.0.39_jobs_response"). The parameterization ensures both the splitting and flat-output behaviors work correctly for these real-world naming patterns, preventing awkward generated filenames like
v0/field_0.py.
Fixes: #1535
Summary by CodeRabbit
Release Notes
New Features
--treat-dot-as-moduleCLI option with tri-state support: explicitly enable with--treat-dot-as-module, explicitly disable with--no-treat-dot-as-module, or omit for default behavior.Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.