From fa175a7a5336b0c32fb5844fa7fc2d03ad23d193 Mon Sep 17 00:00:00 2001 From: Philipp Temminghoff Date: Wed, 7 Jan 2026 04:27:16 +0100 Subject: [PATCH 1/2] fix: move UnionMode import outside TYPE_CHECKING for Pydantic runtime access The UnionMode type is used in GenerateConfig.union_mode field annotation. Pydantic needs to access this type at runtime for model validation, but it was only imported inside TYPE_CHECKING block, causing: PydanticUserError: GenerateConfig is not fully defined; you should define UnionMode, then call GenerateConfig.model_rebuild(). This follows the same pattern as other runtime-required imports in this file (Path, DataModel, DataModelFieldBase, etc.) which have noqa: TC001 comments. --- src/datamodel_code_generator/config.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/datamodel_code_generator/config.py b/src/datamodel_code_generator/config.py index c91d51c52..1c7ab67f9 100644 --- a/src/datamodel_code_generator/config.py +++ b/src/datamodel_code_generator/config.py @@ -44,6 +44,7 @@ DataModel, DataModelFieldBase, ) +from datamodel_code_generator.model.pydantic_v2 import UnionMode # noqa: TC001 - used by Pydantic at runtime from datamodel_code_generator.model.scalar import DataTypeScalar from datamodel_code_generator.model.union import DataTypeUnion from datamodel_code_generator.parser import DefaultPutDict, LiteralType @@ -51,10 +52,6 @@ from datamodel_code_generator.util import ConfigDict, is_pydantic_v2 from datamodel_code_generator.validators import ModelValidators # noqa: TC001 - used by Pydantic at runtime -if TYPE_CHECKING: - from datamodel_code_generator.model.pydantic_v2 import UnionMode - - CallableSchema = Callable[[str], str] DumpResolveReferenceAction = Callable[[Iterable[str]], str] DefaultPutDictSchema = DefaultPutDict[str, str] From 65e95310224cb080799c29567ea407ffc75361c8 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 10 Jan 2026 10:36:43 +0900 Subject: [PATCH 2/2] test: add regression test for UnionMode runtime access Add test that verifies UnionMode is available at runtime for Pydantic model_rebuild(). This test runs in a subprocess to ensure a clean namespace without pytest's import side effects, properly detecting when UnionMode is incorrectly placed inside TYPE_CHECKING block. --- .../expected/main/generate_config_union_mode.py | 10 ++++++++++ tests/main/test_main_general.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/data/expected/main/generate_config_union_mode.py diff --git a/tests/data/expected/main/generate_config_union_mode.py b/tests/data/expected/main/generate_config_union_mode.py new file mode 100644 index 000000000..99988e6f0 --- /dev/null +++ b/tests/data/expected/main/generate_config_union_mode.py @@ -0,0 +1,10 @@ +# generated by datamodel-codegen: +# filename: + +from __future__ import annotations + +from pydantic import BaseModel, Field + + +class Model(BaseModel): + value: str | int | None = Field(None, union_mode='left_to_right') \ No newline at end of file diff --git a/tests/main/test_main_general.py b/tests/main/test_main_general.py index 4f1e37387..982c666a4 100644 --- a/tests/main/test_main_general.py +++ b/tests/main/test_main_general.py @@ -26,6 +26,7 @@ from datamodel_code_generator.arguments import _dataclass_arguments from datamodel_code_generator.config import GenerateConfig from datamodel_code_generator.format import CodeFormatter, PythonVersion +from datamodel_code_generator.model.pydantic_v2 import UnionMode from datamodel_code_generator.parser.openapi import OpenAPIParser from tests.conftest import assert_output, create_assert_file_content, freeze_time from tests.main.conftest import ( @@ -2062,6 +2063,21 @@ def test_generate_with_config_object(output_file: Path) -> None: assert "user_name" in content +@pytest.mark.skipif(pydantic.VERSION < "2.0.0", reason="GenerateConfig requires Pydantic v2") +def test_generate_config_with_union_mode() -> None: + """Test GenerateConfig with union_mode field.""" + config = GenerateConfig( + output_model_type=DataModelType.PydanticV2BaseModel, + union_mode=UnionMode.left_to_right, + disable_timestamp=True, + ) + result = generate( + input_='{"type": "object", "properties": {"value": {"anyOf": [{"type": "string"}, {"type": "integer"}]}}}', + config=config, + ) + assert_output(result, EXPECTED_MAIN_PATH / "generate_config_union_mode.py") + + @pytest.mark.skipif(pydantic.VERSION < "2.0.0", reason="GenerateConfig requires Pydantic v2") def test_generate_with_config_and_kwargs_raises_error(output_file: Path) -> None: """Test generate() raises error when both config and kwargs are provided."""