From 6c5b5f9dfa898e778d2d0960b514eaec228680ba Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 3 Jan 2026 17:24:11 +0000 Subject: [PATCH 1/2] Add deprecation warning for Pydantic v2 without --use-annotated --- docs/cli-reference/typing-customization.md | 2 - pyproject.toml | 1 + src/datamodel_code_generator/__main__.py | 16 +++++++ src/datamodel_code_generator/arguments.py | 5 +- src/datamodel_code_generator/cli_options.py | 1 + tests/main/test_main_general.py | 51 +++++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) diff --git a/docs/cli-reference/typing-customization.md b/docs/cli-reference/typing-customization.md index 24a754f4e..1cf3b21cb 100644 --- a/docs/cli-reference/typing-customization.md +++ b/docs/cli-reference/typing-customization.md @@ -2823,8 +2823,6 @@ syntax instead of default values. This also enables `--field-constraints`. **Related:** [`--field-constraints`](field-customization.md#field-constraints) -**See also:** [Python Version Compatibility](../python-version-compatibility.md) - !!! tip "Usage" ```bash diff --git a/pyproject.toml b/pyproject.toml index 734815bff..2347ac492 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -214,6 +214,7 @@ filterwarnings = [ "error", "ignore:^.*Pydantic v1 runtime support is deprecated.*:DeprecationWarning", "ignore:^.*No --output-model-type specified.*:DeprecationWarning", + "ignore:^.*Pydantic v2 with --use-annotated is recommended.*:DeprecationWarning", "ignore:^.*`--validation` option is deprecated.*", "ignore:^.*--parent-scoped-naming is deprecated.*", "ignore:^.*Field name `name` is duplicated on Pet.*", diff --git a/src/datamodel_code_generator/__main__.py b/src/datamodel_code_generator/__main__.py index 35b6c9421..cfc52f236 100644 --- a/src/datamodel_code_generator/__main__.py +++ b/src/datamodel_code_generator/__main__.py @@ -1209,6 +1209,22 @@ def main(args: Sequence[str] | None = None) -> Exit: # noqa: PLR0911, PLR0912, stacklevel=1, ) + if ( + config.output_model_type in {DataModelType.PydanticV2BaseModel, DataModelType.PydanticV2Dataclass} + and not config.use_annotated + and namespace.use_annotated is None + and pyproject_config.get("use_annotated") is None + ): + warnings.warn( + "Pydantic v2 with --use-annotated is recommended for correct type annotations. " + "The current default (use_annotated=False) generates constrained types like " + "'conint(ge=1, le=365)' which are discouraged in Pydantic v2. " + "In a future version, --use-annotated will be enabled by default for Pydantic v2. " + "Please explicitly specify --use-annotated or --no-use-annotated.", + DeprecationWarning, + stacklevel=1, + ) + if not is_pydantic_v2(): warnings.warn( "Pydantic v1 runtime support is deprecated and will be removed in a future version. " diff --git a/src/datamodel_code_generator/arguments.py b/src/datamodel_code_generator/arguments.py index 0873682bc..bdf680fb9 100644 --- a/src/datamodel_code_generator/arguments.py +++ b/src/datamodel_code_generator/arguments.py @@ -520,8 +520,9 @@ def start_section(self, heading: str | None) -> None: ) typing_options.add_argument( "--use-annotated", - help="Use typing.Annotated for Field(). Also, `--field-constraints` option will be enabled.", - action="store_true", + help="Use typing.Annotated for Field(). Also, `--field-constraints` option will be enabled. " + "Will become default for Pydantic v2 in a future version.", + action=BooleanOptionalAction, default=None, ) typing_options.add_argument( diff --git a/src/datamodel_code_generator/cli_options.py b/src/datamodel_code_generator/cli_options.py index f86846832..570cf73b0 100644 --- a/src/datamodel_code_generator/cli_options.py +++ b/src/datamodel_code_generator/cli_options.py @@ -179,6 +179,7 @@ class CLIOptionMeta: name="--use-generic-container-types", category=OptionCategory.TYPING ), "--use-annotated": CLIOptionMeta(name="--use-annotated", category=OptionCategory.TYPING), + "--no-use-annotated": CLIOptionMeta(name="--no-use-annotated", category=OptionCategory.TYPING), "--use-type-alias": CLIOptionMeta(name="--use-type-alias", category=OptionCategory.TYPING), "--use-root-model-type-alias": CLIOptionMeta(name="--use-root-model-type-alias", category=OptionCategory.TYPING), "--strict-types": CLIOptionMeta(name="--strict-types", category=OptionCategory.TYPING), diff --git a/tests/main/test_main_general.py b/tests/main/test_main_general.py index 86693c902..4f1e37387 100644 --- a/tests/main/test_main_general.py +++ b/tests/main/test_main_general.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from argparse import ArgumentTypeError, Namespace from typing import TYPE_CHECKING @@ -2240,3 +2241,53 @@ def test_custom_formatters_kwargs_invalid(output_file: Path, capsys: pytest.Capt capsys=capsys, expected_stderr_contains="Unable to load custom_formatters_kwargs mapping: must be a JSON string mapping", ) + + +def test_use_annotated_deprecation_warning_pydantic_v2(output_file: Path) -> None: + """Test that deprecation warning is emitted for Pydantic v2 without --use-annotated.""" + with pytest.warns(DeprecationWarning, match=r"--use-annotated will be enabled by default for Pydantic v2"): + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, + input_file_type="jsonschema", + extra_args=["--output-model-type", "pydantic_v2.BaseModel"], + ) + + +def test_use_annotated_no_warning_with_flag(output_file: Path) -> None: + """Test that no warning is emitted when --use-annotated is explicitly set.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, + input_file_type="jsonschema", + extra_args=["--output-model-type", "pydantic_v2.BaseModel", "--use-annotated"], + ) + assert not any("--use-annotated will be enabled" in str(warning.message) for warning in w) + + +def test_use_annotated_no_warning_with_no_flag(output_file: Path) -> None: + """Test that no warning is emitted when --no-use-annotated is explicitly set.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, + input_file_type="jsonschema", + extra_args=["--output-model-type", "pydantic_v2.BaseModel", "--no-use-annotated"], + ) + assert not any("--use-annotated will be enabled" in str(warning.message) for warning in w) + + +def test_use_annotated_no_warning_pydantic_v1(output_file: Path) -> None: + """Test that use_annotated warning is not emitted for Pydantic v1.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, + input_file_type="jsonschema", + extra_args=["--output-model-type", "pydantic.BaseModel"], + ) + assert not any("--use-annotated will be enabled" in str(warning.message) for warning in w) From c71802bd971552a0aff5018407c3d2b9daa4d39f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 3 Jan 2026 17:39:15 +0000 Subject: [PATCH 2/2] docs: update llms.txt files Generated by GitHub Actions --- docs/llms-full.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/llms-full.txt b/docs/llms-full.txt index 46bbdc2d4..f457673dc 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -14224,8 +14224,6 @@ syntax instead of default values. This also enables `--field-constraints`. **Related:** [`--field-constraints`](field-customization.md#field-constraints) -**See also:** [Python Version Compatibility](../python-version-compatibility.md) - !!! tip "Usage" ```bash