Skip to content

[Bug] Doubly defined objects in the output specification #260

@allComputableThings

Description

@allComputableThings

When we have:

@component
@dataclasses.dataclass
class Location:
    x: int
    y: int
@component
@dataclasses.dataclass
class UserProfile:
    name: str
    age: int
    email: str
    location: Location #Path

Location is define twice in the output schema. Once in components, once again within UserProfile.

This is deeply problematic for code generators which depend on generating a single class for both. ( openapi-generator-cli, for example, produces two Location classes and one cannot be used where the other is used).

UserProfile should have a ref to Location and Location should be added as a component whether or not it has the @component decorator:

{
   "$ref": f"#/components/schemas/{Location.__name__}"
}
import os
import dataclasses

from sanic import Sanic, text, Request
from sanic_ext.extensions.openapi import openapi
from sanic_ext.extensions.openapi.definitions import Response, RequestBody
from sanic_ext.extensions.openapi.openapi import component

# from typing import List

app = Sanic("app")

@component
@dataclasses.dataclass
class MyBody:
    email: str
    # @property
    # def something(self) -> int:
    #     print("Oh no you didn't!")
    #     return "OK2"

@component
@dataclasses.dataclass
class Location:
    x: int
    y: int


@component
@dataclasses.dataclass
class UserProfile:
    name: str
    age: int
    email: str
    # locations: List[Location] #Path
    location: Location #Path

    @property
    def something(self) -> int:
        print("Oh no you didn't!")
        return "OK"




@app.post("/")
@openapi.definition(
    body=RequestBody({"application/json": {
                    "$ref": f"#/components/schemas/{MyBody.__name__}"
                }}, required=True),  # if body else None,
    # body=RequestBody(Body, required=True),
    # summary="User profile update",
    # tag="one",
    # description=openapi.description(textwrap.dedent(func.__doc__)) if func.__doc__ else None,
    response=[  # Success,
        Response({
            "application/json": {
                "schema": {
                    "$ref": f"#/components/schemas/{UserProfile.__name__}"
                }
            }
        }, status=200)
        # Response(Failure, status=400)
    ],
)
def root(req: Request, *args, **kw):  # body:UserProfile):
    """
    Short description

    Long Description
    """
    return text("Hello")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions