koxudaxi / datamodel-code-generator

Pydantic model and dataclasses.dataclass generator for easy conversion of JSON, OpenAPI, JSON Schema, and YAML data sources.
https://koxudaxi.github.io/datamodel-code-generator/
MIT License
2.65k stars 296 forks source link

Schemas with the same name in the path do not create valid models #1994

Open piercsi opened 3 months ago

piercsi commented 3 months ago

Schemas with the same name in the path do not create valid models

This specifically happens when both:

To reproduce:

the following error is raised:

C:\Users\MyProject\.venv\Scripts\python.exe C:\Users\MyProject\main.py 
Traceback (most recent call last):
  File "C:\Users\MyProject\main.py", line 1, in <module>
    import model
  File "C:\Users\MyProject\model\__init__.py", line 14, in <module>
    class AGetResponse(RootModel[List[A]]):
                       ~~~~~~~~~^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\main.py", line 730, in __class_getitem__
    submodel = _generics.create_generic_submodel(model_name, origin, args, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generics.py", line 138, in create_generic_submodel
    created_model = meta(
                    ^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 202, in __new__
    complete_model_class(
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 539, in complete_model_class
    schema = cls.__get_pydantic_core_schema__(cls, handler)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\main.py", line 626, in __get_pydantic_core_schema__
    return handler(source)
           ^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 82, in __call__
    schema = self._handler(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 502, in generate_schema
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 753, in _generate_schema_inner
    return self._model_schema(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 565, in _model_schema
    root_field = self._common_field_schema('root', fields['root'], decorators)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1081, in _common_field_schema
    schema = self._apply_annotations(
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1825, in _apply_annotations
    schema = get_inner_schema(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 82, in __call__
    schema = self._handler(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1907, in new_handler
    schema = metadata_get_schema(source, get_inner_schema)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_std_types_schema.py", line 314, in __get_pydantic_core_schema__
    items_schema = handler.generate_schema(self.item_source_type)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 96, in generate_schema
    return self._generate_schema.generate_schema(source_type)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 502, in generate_schema
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 758, in _generate_schema_inner
    return self.match_type(obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 844, in match_type
    return self._unknown_type_schema(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\MyProject\.venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 405, in _unknown_type_schema
    raise PydanticSchemaGenerationError(
pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <module 'model.A' from 'C:\\Users\\MyProject\\model\\A.py'>. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.

If you got this error by calling handler(<some type>) within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema(<some type>)` since we do not call `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.

For further information visit https://errors.pydantic.dev/2.7/u/schema-for-unknown-type

Example schema:

{
  "openapi": "3.0.1",
  "paths": {
    "/a": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/A.A"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "A.A": {
        "type": "object"
      }
    }
  }
}

Used commandline:

$ datamodel-codegen --input swagger.json --input-file-type openapi --output model --output-model-type pydantic_v2.BaseModel --openapi-scopes {schemas,paths}

Expected behavior A valid model is created that can be used without an exception being raised.

Version: