From 0f79b4d6d1cd683714ea9edd6f7c0adb8e3f0ce9 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 12 Jan 2026 15:06:56 +0000 Subject: [PATCH 1/2] Add GenerateConfig lazy import from top-level module --- docs/using_as_module.md | 5 ++++ src/datamodel_code_generator/__init__.py | 11 ++++++++ tests/main/test_main_general.py | 33 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/docs/using_as_module.md b/docs/using_as_module.md index cdfa104d7..bcb45f111 100644 --- a/docs/using_as_module.md +++ b/docs/using_as_module.md @@ -16,6 +16,11 @@ pip install 'datamodel-code-generator[http]' When the `output` parameter is omitted (or set to `None`), `generate()` returns the generated code directly as a string: +!!! note + `GenerateConfig` is only available in Pydantic v2 environments. + For Pydantic v1, use `from datamodel_code_generator.config import GenerateConfig` + and call `update_forward_refs()` before use. + ```python from datamodel_code_generator import InputFileType, generate, GenerateConfig, DataModelType diff --git a/src/datamodel_code_generator/__init__.py b/src/datamodel_code_generator/__init__.py index 23a79bf21..8417a03fb 100644 --- a/src/datamodel_code_generator/__init__.py +++ b/src/datamodel_code_generator/__init__.py @@ -971,6 +971,7 @@ def infer_input_type(text: str) -> InputFileType: "detect_jsonschema_version": "datamodel_code_generator.parser.schema_version", "detect_openapi_version": "datamodel_code_generator.parser.schema_version", "generate_dynamic_models": "datamodel_code_generator.dynamic", + "GenerateConfig": "datamodel_code_generator.config", } @@ -978,6 +979,13 @@ def __getattr__(name: str) -> Any: if name in _LAZY_IMPORTS: import importlib # noqa: PLC0415 + if name == "GenerateConfig" and not is_pydantic_v2(): # pragma: no cover + msg = ( + f"'{name}' is only available in Pydantic v2 environments. " + "Use 'from datamodel_code_generator.config import GenerateConfig' instead." + ) + raise ImportError(msg) + module = importlib.import_module(_LAZY_IMPORTS[name]) return getattr(module, name) msg = f"module {__name__!r} has no attribute {name!r}" @@ -1025,3 +1033,6 @@ def __getattr__(name: str) -> Any: "generate", "generate_dynamic_models", # noqa: F822 ] + +if is_pydantic_v2(): # pragma: no cover + __all__ += ["GenerateConfig"] diff --git a/tests/main/test_main_general.py b/tests/main/test_main_general.py index 982c666a4..2021939e6 100644 --- a/tests/main/test_main_general.py +++ b/tests/main/test_main_general.py @@ -11,6 +11,7 @@ import pytest from inline_snapshot import snapshot +import datamodel_code_generator from datamodel_code_generator import ( AllExportsScope, DataModelType, @@ -28,6 +29,7 @@ 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 datamodel_code_generator.util import is_pydantic_v2 from tests.conftest import assert_output, create_assert_file_content, freeze_time from tests.main.conftest import ( DATA_PATH, @@ -2307,3 +2309,34 @@ def test_use_annotated_no_warning_pydantic_v1(output_file: Path) -> None: extra_args=["--output-model-type", "pydantic.BaseModel"], ) assert not any("--use-annotated will be enabled" in str(warning.message) for warning in w) + + +@pytest.mark.skipif(not is_pydantic_v2(), reason="GenerateConfig requires Pydantic v2") +def test_import_generate_config_from_top_level() -> None: + """Test that GenerateConfig can be imported from top-level module.""" + from datamodel_code_generator import GenerateConfig as TopLevelGenerateConfig + + assert TopLevelGenerateConfig is not None + assert TopLevelGenerateConfig is GenerateConfig + + +@pytest.mark.skipif(not is_pydantic_v2(), reason="GenerateConfig requires Pydantic v2") +def test_generate_with_imported_config_from_top_level() -> None: + """Test generate() with GenerateConfig imported from top-level.""" + config = datamodel_code_generator.GenerateConfig(class_name="TestModel") + result = generate('{"type": "object"}', config=config) + assert result is not None + assert "class TestModel" in result + + +@pytest.mark.skipif(not is_pydantic_v2(), reason="GenerateConfig requires Pydantic v2") +def test_all_exports_includes_generate_config() -> None: + """Test that __all__ includes GenerateConfig in Pydantic v2.""" + assert "GenerateConfig" in datamodel_code_generator.__all__ + + +@pytest.mark.skipif(is_pydantic_v2(), reason="Test for Pydantic v1 only") +def test_import_generate_config_fails_on_v1() -> None: + """GenerateConfig should not be importable from top-level in Pydantic v1.""" + with pytest.raises(ImportError, match="only available in Pydantic v2"): + _ = datamodel_code_generator.GenerateConfig From 85d20ff7cb4ad838f8efd0364e2b69839118ef8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 12 Jan 2026 15:24:49 +0000 Subject: [PATCH 2/2] docs: update llms.txt files Generated by GitHub Actions --- docs/llms-full.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/llms-full.txt b/docs/llms-full.txt index 3a8bf1abf..91cfa8eae 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -28917,6 +28917,11 @@ pip install 'datamodel-code-generator[http]' When the `output` parameter is omitted (or set to `None`), `generate()` returns the generated code directly as a string: +!!! note + `GenerateConfig` is only available in Pydantic v2 environments. + For Pydantic v1, use `from datamodel_code_generator.config import GenerateConfig` + and call `update_forward_refs()` before use. + ```python from datamodel_code_generator import InputFileType, generate, GenerateConfig, DataModelType