Skip to content

Commit 03200be

Browse files
authored
feat: switch default output model to pydantic v2 (#3029)
1 parent 3bedaaa commit 03200be

11 files changed

Lines changed: 78 additions & 26 deletions

File tree

src/datamodel_code_generator/__main__.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def validate_class_name_affix_scope(cls, v: str | ClassNameAffixScope | None) ->
420420
input_model: Optional[list[str]] = None # noqa: UP045
421421
input_model_ref_strategy: Optional[InputModelRefStrategy] = None # noqa: UP045
422422
input_file_type: InputFileType = InputFileType.Auto
423-
output_model_type: DataModelType = DataModelType.PydanticBaseModel
423+
output_model_type: DataModelType = DataModelType.PydanticV2BaseModel
424424
output: Optional[Path] = None # noqa: UP045
425425
check: bool = False
426426
debug: bool = False
@@ -1127,22 +1127,6 @@ def main(args: Sequence[str] | None = None) -> Exit: # noqa: PLR0911, PLR0912,
11271127
if config.disable_warnings:
11281128
warnings.simplefilter("ignore")
11291129

1130-
if (
1131-
namespace.output_model_type is None
1132-
and pyproject_config.get("output_model_type") is None
1133-
and config.output_model_type == DataModelType.PydanticBaseModel
1134-
):
1135-
warnings.warn(
1136-
"No --output-model-type specified. "
1137-
"The current default (pydantic.BaseModel, Pydantic v1) is deprecated "
1138-
"and will be removed in a future version. "
1139-
"Please explicitly specify --output-model-type. "
1140-
"Example: --output-model-type pydantic_v2.BaseModel. "
1141-
"See https://github.com/koxudaxi/datamodel-code-generator/issues/2466",
1142-
DeprecationWarning,
1143-
stacklevel=1,
1144-
)
1145-
11461130
if (
11471131
config.output_model_type in {DataModelType.PydanticV2BaseModel, DataModelType.PydanticV2Dataclass}
11481132
and not config.use_annotated

src/datamodel_code_generator/arguments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def start_section(self, heading: str | None) -> None:
177177
)
178178
base_options.add_argument(
179179
"--output-model-type",
180-
help="Output model type (default: pydantic.BaseModel)",
180+
help="Output model type (default: pydantic_v2.BaseModel)",
181181
choices=[i.value for i in DataModelType],
182182
)
183183
base_options.add_argument(

src/datamodel_code_generator/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class GenerateConfig(BaseModel):
6868
input_filename: str | None = None
6969
input_file_type: InputFileType = InputFileType.Auto
7070
output: Path | None = None
71-
output_model_type: DataModelType = DataModelType.PydanticBaseModel
71+
output_model_type: DataModelType = DataModelType.PydanticV2BaseModel
7272
target_python_version: PythonVersion = PythonVersionMin
7373
target_pydantic_version: TargetPydanticVersion | None = None
7474
base_class: str = ""

src/datamodel_code_generator/input_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ def load_model_schema( # noqa: PLR0912, PLR0914, PLR0915
705705
from datamodel_code_generator.arguments import InputModelRefStrategy # noqa: PLC0415
706706

707707
if output_model_type is None:
708-
output_model_type = DataModelType.PydanticBaseModel
708+
output_model_type = DataModelType.PydanticV2BaseModel
709709

710710
if len(input_models) == 1:
711711
return _load_single_model_schema(input_models[0], input_file_type, ref_strategy, output_model_type)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# generated by datamodel-codegen:
2+
# filename: space_and_special_characters_dict.py
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from pydantic import BaseModel, Field
8+
9+
10+
class InitialParameters(BaseModel):
11+
V1: int
12+
V2: int
13+
14+
15+
class Data(BaseModel):
16+
Length__m_: float = Field(..., alias='Length (m)')
17+
Symmetric_deviation____: float = Field(..., alias='Symmetric deviation (%)')
18+
Total_running_time__s_: int = Field(..., alias='Total running time (s)')
19+
Mass__kg_: float = Field(..., alias='Mass (kg)')
20+
Initial_parameters: InitialParameters = Field(..., alias='Initial parameters')
21+
class_: str = Field(..., alias='class')
22+
23+
24+
class Values(BaseModel):
25+
field_1_Step: str = Field(..., alias='1 Step')
26+
field_2_Step: str = Field(..., alias='2 Step')
27+
28+
29+
class Recursive1(BaseModel):
30+
value: float
31+
32+
33+
class Sub(BaseModel):
34+
recursive: Recursive1
35+
36+
37+
class Recursive(BaseModel):
38+
sub: Sub
39+
40+
41+
class Model(BaseModel):
42+
Serial_Number: str = Field(..., alias='Serial Number')
43+
Timestamp: str
44+
Data_1: Data = Field(..., alias='Data')
45+
values: Values
46+
recursive: Recursive

tests/main/conftest.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,11 @@ def run_main_and_assert( # noqa: PLR0912
470470
assert_func(output_path, expected_file, transform=transform)
471471

472472
if output_path is not None and not skip_code_validation:
473-
_validate_output_files(output_path, extra_args, force_exec_validation=force_exec_validation)
473+
normalized_extra_args = _normalize_extra_args(
474+
extra_args,
475+
default_output_model_type=default_output_model_type,
476+
)
477+
_validate_output_files(output_path, normalized_extra_args, force_exec_validation=force_exec_validation)
474478

475479

476480
def _parse_target_version(extra_arguments: Sequence[str] | None) -> tuple[int, int] | None:
@@ -500,7 +504,7 @@ def _should_skip_exec(extra_arguments: Sequence[str] | None, *, force_exec: bool
500504
When target > runtime, compile will be skipped entirely regardless of this flag.
501505
"""
502506
output_model_type = _get_argument_value(extra_arguments, "--output-model-type")
503-
is_pydantic_v1 = output_model_type is None or output_model_type == DataModelType.PydanticBaseModel.value
507+
is_pydantic_v1 = output_model_type == DataModelType.PydanticBaseModel.value
504508
if (is_pydantic_v1 and is_pydantic_v2()) or (
505509
output_model_type in {DataModelType.PydanticV2BaseModel.value, DataModelType.PydanticV2Dataclass.value}
506510
and not is_pydantic_v2()
@@ -601,6 +605,7 @@ def run_main_url_and_assert(
601605
assert_func: AssertFileContent,
602606
expected_file: str | Path,
603607
extra_args: Sequence[str] | None = None,
608+
default_output_model_type: str | None = DataModelType.PydanticBaseModel.value,
604609
transform: Callable[[str], str] | None = None,
605610
force_exec_validation: bool = False,
606611
) -> None:
@@ -613,13 +618,26 @@ def run_main_url_and_assert(
613618
assert_func: The assert_file_content function to use for verification
614619
expected_file: Expected output filename
615620
extra_args: Additional CLI arguments
621+
default_output_model_type: Output model type injected when extra_args omits
622+
--output-model-type. Set to None for tests that intentionally validate
623+
the real CLI default.
616624
transform: Optional function to transform output before comparison
617625
force_exec_validation: Run exec() even when target Python version differs from
618626
the test environment (only effective when target <= runtime).
619627
"""
620628
__tracebackhide__ = True
621-
return_code = _run_main_url(url, output_path, input_file_type, extra_args=extra_args)
629+
return_code = _run_main_url(
630+
url,
631+
output_path,
632+
input_file_type,
633+
extra_args=extra_args,
634+
default_output_model_type=default_output_model_type,
635+
)
622636
_assert_exit_code(return_code, Exit.OK, f"URL: {url}")
623637
assert_func(output_path, expected_file, transform=transform)
624638

625-
_validate_output_files(output_path, extra_args, force_exec_validation=force_exec_validation)
639+
normalized_extra_args = _normalize_extra_args(
640+
extra_args,
641+
default_output_model_type=default_output_model_type,
642+
)
643+
_validate_output_files(output_path, normalized_extra_args, force_exec_validation=force_exec_validation)

tests/main/jsonschema/test_main_jsonschema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,7 @@ def test_main_generate_from_directory(tmp_path: Path) -> None:
20102010
input_=input_,
20112011
input_file_type=InputFileType.JsonSchema,
20122012
output=tmp_path,
2013+
output_model_type=DataModelType.PydanticBaseModel,
20132014
)
20142015

20152016
main_nested_directory = EXPECTED_JSON_SCHEMA_PATH / "nested_directory"

tests/main/openapi/test_main_openapi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,6 +1767,7 @@ def custom_class_name_generator(name: str) -> str:
17671767
input_=input_,
17681768
input_file_type=InputFileType.OpenAPI,
17691769
output=output_path,
1770+
output_model_type=DataModelType.PydanticBaseModel,
17701771
custom_class_name_generator=custom_class_name_generator,
17711772
)
17721773

tests/main/test_main_general.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ def test_space_and_special_characters_dict(output_file: Path) -> None:
112112
output_path=output_file,
113113
input_file_type="dict",
114114
assert_func=assert_file_content,
115+
expected_file="space_and_special_characters_dict_default_v2.py",
115116
default_output_model_type=None,
116117
)
117118

@@ -1827,6 +1828,7 @@ def test_generate_returns_dict_for_multiple_modules(tmp_path: Path) -> None:
18271828
tmp_path,
18281829
input_file_type=InputFileType.JsonSchema,
18291830
disable_timestamp=True,
1831+
output_model_type=DataModelType.PydanticBaseModel,
18301832
)
18311833

18321834
assert result == snapshot({

tests/main/test_public_api_signature_baseline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def _baseline_generate(
6262
input_filename: str | None = None,
6363
input_file_type: InputFileType = InputFileType.Auto,
6464
output: Path | None = None,
65-
output_model_type: DataModelType = DataModelType.PydanticBaseModel,
65+
output_model_type: DataModelType = DataModelType.PydanticV2BaseModel,
6666
target_python_version: PythonVersion = PythonVersionMin,
6767
target_pydantic_version: TargetPydanticVersion | None = None,
6868
base_class: str = "",

0 commit comments

Comments
 (0)