Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect schema for generic classes that override model_generic_name #25

Closed
gorilla-seb opened this issue Oct 16, 2023 · 1 comment
Closed

Comments

@gorilla-seb
Copy link

When using generic models that override model_generic_name to generate a custom name for their generated concrete classes, the generated schema is invalid: the $refuses the custom name, but schema does not. Script to reproduce:

from typing import Any, Generic, TypeVar

from openapi_pydantic import Info, MediaType, OpenAPI, Operation, PathItem, Response
from openapi_pydantic.util import PydanticSchema, construct_open_api_with_schema_class
from pydantic import BaseModel

T_ = TypeVar("T_")


class Foo(BaseModel):
    foo: str


class Bar(BaseModel, Generic[T_]):
    data: list[T_]

    @classmethod
    def model_parametrized_name(cls: type[Any], params: tuple[type[Any], ...]) -> str:
        return f"{params[0].__name__}Bar"


Paths = {
    "/foo": PathItem(
        get=Operation(
            operationId="getFoos",
            summary="Get all foos",
            description="Fetches a paged list of foos",
            responses={
                "200": Response(
                    description="List of foos",
                    content={
                        "application/json": MediaType(
                            schema=PydanticSchema(schema_class=Bar[Foo])
                        )
                    },
                )
            },
        ),
    )
}


spec = OpenAPI(info=Info(title="TestSchema", version="1"), paths=Paths)
oas = construct_open_api_with_schema_class(spec)
oas_json = oas.model_dump_json(by_alias=True, exclude_none=True, indent=2)
print(oas_json)

Result:

{
  "openapi": "3.1.0",
  "info": {
    "title": "TestSchema",
    "version": "1"
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "paths": {
    "/foo": {
      "get": {
        "summary": "Get all foos",
        "description": "Fetches a paged list of foos",
        "operationId": "getFoo",
        "responses": {
          "200": {
            "description": "List of foos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FooBar"
                }
              }
            }
          }
        },
        "deprecated": false
      }
    }
  },
  "components": {
    "schemas": {
      "Bar_Foo_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/Foo"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "FooBar"
      },
      "Foo": {
        "properties": {
          "foo": {
            "type": "string",
            "title": "Foo"
          }
        },
        "type": "object",
        "required": [
          "foo"
        ],
        "title": "Foo"
      }
    }
  }
}

This may be related to pydantic/pydantic#7376 . I've added a quick and dirty workaround here: gorilla-seb@099cbbc

@mike-oakley
Copy link
Owner

Hey @gorilla-seb - thanks for raising! I think this indeed would better be fixed in Pydantic itself - seems like there is some work already on this in pydantic/pydantic#6304. Going to close this one out for now as that seems like the fix to wait for here 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants