From 003cf6282978062a65d719b26b5e9524e1a98806 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 10 Jan 2026 06:12:18 +0000 Subject: [PATCH 1/2] Fix IndexError when using --reuse-scope=tree with single file output --- src/datamodel_code_generator/parser/base.py | 2 +- tests/data/openapi/issue_2953.yaml | 65 +++++++++++++++++++++ tests/main/openapi/test_main_openapi.py | 24 ++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/data/openapi/issue_2953.yaml diff --git a/src/datamodel_code_generator/parser/base.py b/src/datamodel_code_generator/parser/base.py index 4ff277520..d563fab9d 100644 --- a/src/datamodel_code_generator/parser/base.py +++ b/src/datamodel_code_generator/parser/base.py @@ -1752,7 +1752,7 @@ def __validate_shared_module_name( ) -> None: """Validate that the shared module name doesn't conflict with existing modules.""" shared_module = self.shared_module_name - existing_module_names = {module[0] for module, _ in module_models} + existing_module_names = {module[0] for module, _ in module_models if module} if shared_module in existing_module_names: msg = ( f"Schema file or directory '{shared_module}' conflicts with the shared module name. " diff --git a/tests/data/openapi/issue_2953.yaml b/tests/data/openapi/issue_2953.yaml new file mode 100644 index 000000000..9b3abc8a2 --- /dev/null +++ b/tests/data/openapi/issue_2953.yaml @@ -0,0 +1,65 @@ +openapi: "3.0.0" +info: + title: Issue 2953 Test + version: "1.0.0" +components: + schemas: + Collection-Wrapper: + description: Generic response wrapper containing a collection of items and pagination metadata. + type: object + required: + - data + - pagination + properties: + data: + description: Array of items in the collection. + type: array + items: + type: object + pagination: + description: Pagination metadata for the collection. + $ref: "#/components/schemas/Metadata" + DataType: + type: object + required: + - id + properties: + property_1: + type: string + format: uuid + readOnly: true + description: Unique identifier for the installation. + property_2: + type: string + description: Description of the installation. + property_3: + type: string + format: date-time + readOnly: true + description: Timestamp when the installation was created. + + PaginatedDataTypeList: + allOf: + - properties: + data: + type: array + items: + $ref: "#/components/schemas/DataType" + - $ref: "#/components/schemas/Collection-Wrapper" + Metadata: + type: object + required: + - limit + - page + properties: + limit: + type: integer + minimum: 1 + maximum: 100 + description: Number of data types returned in this response + example: 20 + page: + type: integer + minimum: 1 + description: The page number to retrieve + example: 2 diff --git a/tests/main/openapi/test_main_openapi.py b/tests/main/openapi/test_main_openapi.py index 47cf8e3d2..82c680e07 100644 --- a/tests/main/openapi/test_main_openapi.py +++ b/tests/main/openapi/test_main_openapi.py @@ -4939,3 +4939,27 @@ def test_main_openapi_deprecated_field(output_file: Path) -> None: expected_file="deprecated_field.py", extra_args=["--output-model-type", "pydantic_v2.BaseModel"], ) + + +def test_main_openapi_reuse_scope_tree_single_file_error(capsys: pytest.CaptureFixture[str], output_file: Path) -> None: + """Test --reuse-scope=tree with single file output raises proper error (#2953). + + When using reuse-scope=tree with single file output and duplicate models, + it should raise a proper error about needing a directory output instead of + crashing with IndexError. + """ + run_main_and_assert( + input_path=OPEN_API_DATA_PATH / "issue_2953.yaml", + output_path=output_file, + input_file_type="openapi", + expected_exit=Exit.ERROR, + capsys=capsys, + expected_stderr_contains="Modular references require an output directory, not a file", + extra_args=[ + "--output-model-type", + "pydantic_v2.BaseModel", + "--reuse-model", + "--reuse-scope", + "tree", + ], + ) From 6c8aa369187487a3acb06d2462d844846cc46a82 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 10 Jan 2026 07:06:58 +0000 Subject: [PATCH 2/2] Add SKIP_PYDANTIC_V1 decorator to pydantic v2 test --- tests/main/openapi/test_main_openapi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/main/openapi/test_main_openapi.py b/tests/main/openapi/test_main_openapi.py index 82c680e07..1b712dc85 100644 --- a/tests/main/openapi/test_main_openapi.py +++ b/tests/main/openapi/test_main_openapi.py @@ -4941,6 +4941,7 @@ def test_main_openapi_deprecated_field(output_file: Path) -> None: ) +@SKIP_PYDANTIC_V1 def test_main_openapi_reuse_scope_tree_single_file_error(capsys: pytest.CaptureFixture[str], output_file: Path) -> None: """Test --reuse-scope=tree with single file output raises proper error (#2953).