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..1b712dc85 100644 --- a/tests/main/openapi/test_main_openapi.py +++ b/tests/main/openapi/test_main_openapi.py @@ -4939,3 +4939,28 @@ def test_main_openapi_deprecated_field(output_file: Path) -> None: expected_file="deprecated_field.py", extra_args=["--output-model-type", "pydantic_v2.BaseModel"], ) + + +@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). + + 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", + ], + )