Skip to content

Commit fa1fc11

Browse files
phil65koxudaxi
andauthored
fix: move UnionMode import outside TYPE_CHECKING for Pydantic runtime… (#2950)
* 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. * 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. --------- Co-authored-by: Koudai Aono <[email protected]>
1 parent 4decf36 commit fa1fc11

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

src/datamodel_code_generator/config.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,14 @@
4444
DataModel,
4545
DataModelFieldBase,
4646
)
47+
from datamodel_code_generator.model.pydantic_v2 import UnionMode # noqa: TC001 - used by Pydantic at runtime
4748
from datamodel_code_generator.model.scalar import DataTypeScalar
4849
from datamodel_code_generator.model.union import DataTypeUnion
4950
from datamodel_code_generator.parser import DefaultPutDict, LiteralType
5051
from datamodel_code_generator.types import DataTypeManager, StrictTypes # noqa: TC001 - used by Pydantic at runtime
5152
from datamodel_code_generator.util import ConfigDict, is_pydantic_v2
5253
from datamodel_code_generator.validators import ModelValidators # noqa: TC001 - used by Pydantic at runtime
5354

54-
if TYPE_CHECKING:
55-
from datamodel_code_generator.model.pydantic_v2 import UnionMode
56-
57-
5855
CallableSchema = Callable[[str], str]
5956
DumpResolveReferenceAction = Callable[[Iterable[str]], str]
6057
DefaultPutDictSchema = DefaultPutDict[str, str]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# generated by datamodel-codegen:
2+
# filename: <stdin>
3+
4+
from __future__ import annotations
5+
6+
from pydantic import BaseModel, Field
7+
8+
9+
class Model(BaseModel):
10+
value: str | int | None = Field(None, union_mode='left_to_right')

tests/main/test_main_general.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from datamodel_code_generator.arguments import _dataclass_arguments
2727
from datamodel_code_generator.config import GenerateConfig
2828
from datamodel_code_generator.format import CodeFormatter, PythonVersion
29+
from datamodel_code_generator.model.pydantic_v2 import UnionMode
2930
from datamodel_code_generator.parser.openapi import OpenAPIParser
3031
from tests.conftest import assert_output, create_assert_file_content, freeze_time
3132
from tests.main.conftest import (
@@ -2062,6 +2063,21 @@ def test_generate_with_config_object(output_file: Path) -> None:
20622063
assert "user_name" in content
20632064

20642065

2066+
@pytest.mark.skipif(pydantic.VERSION < "2.0.0", reason="GenerateConfig requires Pydantic v2")
2067+
def test_generate_config_with_union_mode() -> None:
2068+
"""Test GenerateConfig with union_mode field."""
2069+
config = GenerateConfig(
2070+
output_model_type=DataModelType.PydanticV2BaseModel,
2071+
union_mode=UnionMode.left_to_right,
2072+
disable_timestamp=True,
2073+
)
2074+
result = generate(
2075+
input_='{"type": "object", "properties": {"value": {"anyOf": [{"type": "string"}, {"type": "integer"}]}}}',
2076+
config=config,
2077+
)
2078+
assert_output(result, EXPECTED_MAIN_PATH / "generate_config_union_mode.py")
2079+
2080+
20652081
@pytest.mark.skipif(pydantic.VERSION < "2.0.0", reason="GenerateConfig requires Pydantic v2")
20662082
def test_generate_with_config_and_kwargs_raises_error(output_file: Path) -> None:
20672083
"""Test generate() raises error when both config and kwargs are provided."""

0 commit comments

Comments
 (0)