openapi-schema-pydantic icon indicating copy to clipboard operation
openapi-schema-pydantic copied to clipboard

parse_obj cuts off definitions

Open manycoding opened this issue 2 years ago • 3 comments

I noticed that ref definitions are not present in the parse_obj result.

To reproduce:

from typing import *

from pydantic import Field
from openapi_schema_pydantic import OpenAPI
from pydantic.schema import schema as create_schema

schema = {
    "info": {"title": "My own API", "version": "v0.0.1"},
    "paths": {
        "/ping": {
            "post": {
                    "requestBody": {"content": {"application/json": {
                        "schema": ""
                    }}},
                    "responses": {"200": {"description": "pong"}
                    },
                }
        }
    },
    "components": {"schemas": {}}
}
schema["paths"]["/ping"]["post"]["requestBody"]["content"]["application/json"]["schema"] = DocumentPUTParameters.schema()

>>> DocumentPUTParameters.schema()
{'title': 'DocumentPUTParameters', 'type': 'object', 'properties': {'payment': {'$ref': '#/definitions/PaymentPUTParameters'}}, 'additionalProperties': False, 'definitions': {'PaymentPUTParameters': {'title': 'PaymentPUTParameters', 'type': 'object', 'properties': {'terms': {'title': 'Terms', 'example': '15 days', 'type': 'string'}}, 'additionalProperties': False}}}

>>> create_schema([DocumentPUTParameters], ref_prefix="#/components/schemas/" )
{'definitions': {'PaymentPUTParameters': {'title': 'PaymentPUTParameters', 'type': 'object', 'properties': {'terms': {'title': 'Terms', 'example': '15 days', 'type': 'string'}}, 'additionalProperties': False}, 'DocumentPUTParameters': {'title': 'DocumentPUTParameters', 'type': 'object', 'properties': {'payment': {'$ref': '#/components/schemas/PaymentPUTParameters'}}, 'additionalProperties': False}}}

schema
{'info': {'title': 'My own API', 'version': 'v0.0.1'}, 'paths': {'/ping': {'post': {'requestBody': {'content': {'application/json': {'schema': {'title': 'DocumentPUTParameters', 'type': 'object', 'properties': {'payment': {'$ref': '#/definitions/PaymentPUTParameters'}}, 'additionalProperties': False, 'definitions': {'PaymentPUTParameters': {'title': 'PaymentPUTParameters', 'type': 'object', 'properties': {'terms': {'title': 'Terms', 'example': '15 days', 'type': 'string'}}, 'additionalProperties': False}}}}}}, 'responses': {'200': {'description': 'pong'}}}}}, 'components': {'schemas': {}}}

>>>OpenAPI.parse_obj(schema)
OpenAPI(openapi='3.1.0', info=Info(title='My own API', summary=None, description=None, termsOfService=None, contact=None, license=None, version='v0.0.1'), jsonSchemaDialect=None, servers=[Server(url='/', description=None, variables=None)], paths={'/ping': PathItem(ref=None, summary=None, description=None, get=None, put=None, post=Operation(tags=None, summary=None, description=None, externalDocs=None, operationId=None, parameters=None, requestBody=RequestBody(description=None, content={'application/json': MediaType(media_type_schema=Schema(allOf=None, anyOf=None, oneOf=None, schema_not=None, schema_if=None, then=None, schema_else=None, dependentSchemas=None, prefixItems=None, items=None, contains=None, properties={'payment': Reference(ref='#/definitions/PaymentPUTParameters', summary=None, description=None)}, patternProperties=None, additionalProperties=False, propertyNames=None, unevaluatedItems=None, unevaluatedProperties=None, type='object', enum=None, const=None, multipleOf=None, maximum=None, exclusiveMaximum=None, minimum=None, exclusiveMinimum=None, maxLength=None, minLength=None, pattern=None, maxItems=None, minItems=None, uniqueItems=None, maxContains=None, minContains=None, maxProperties=None, minProperties=None, required=None, dependentRequired=None, schema_format=None, contentEncoding=None, contentMediaType=None, contentSchema=None, title='DocumentPUTParameters', description=None, default=None, deprecated=None, readOnly=None, writeOnly=None, examples=None, discriminator=None, xml=None, externalDocs=None, example=None), example=None, examples=None, encoding=None)}, required=False), responses={'200': Response(description='pong', headers=None, content=None, links=None)}, callbacks=None, deprecated=False, security=None, servers=None), delete=None, options=None, head=None, patch=None, trace=None, servers=None, parameters=None)}, webhooks=None, components=Components(schemas={}, responses=None, parameters=None, examples=None, requestBodies=None, headers=None, securitySchemes=None, links=None, callbacks=None, pathItems=None), security=None, tags=None, externalDocs=None)

As you can see, PaymentPUTParameters definition is missing from parse_obj result.

manycoding avatar May 27 '22 18:05 manycoding

Please refer to https://github.com/kuimono/openapi-schema-pydantic#use-pydantic-classes-as-schema on how to use PydanticSchema objects to represent the Schema in OpenAPI object

kuimono avatar May 30 '22 12:05 kuimono

@kuimono Thanks, but you didn't answer why parse_obj behaves in unexpected way.

I checked PydanticSchema and it has the same problem - seems like there's no support for Pedantic schemas which reference other Pedantic schemas.

manycoding avatar May 30 '22 15:05 manycoding

A slight change to reproduce - payment terms are missing:

from typing import *

from pydantic import Field
from openapi_schema_pydantic import OpenAPI
from openapi_schema_pydantic.util import PydanticSchema, construct_open_api_with_schema_class
from pydantic import BaseModel


class PaymentPUTParameters(BaseModel):
    terms: Optional[str] = Field(example="15 days")


class DocumentPUTParameters(BaseModel):
    payment: Optional[PaymentPUTParameters] = Field()

schema = {
    "info": {"title": "My own API", "version": "v0.0.1"},
    "paths": {
        "/ping": {
            "post": {
                    "requestBody": {"content": {"application/json": {
                        "schema": PydanticSchema(schema_class=DocumentPUTParameters)
                    }}},
                    "responses": {"200": {"description": "pong"}
                    },
                }
        }
    },
    "components": {"schemas": {}}
}
>>>OpenAPI.parse_obj(schema)

OpenAPI.parse_obj(schema)
OpenAPI(openapi='3.1.0', info=Info(title='My own API', summary=None, description=None, termsOfService=None, contact=None, license=None, version='v0.0.1'), jsonSchemaDialect=None, servers=[Server(url='/', description=None, variables=None)], paths={'/ping': PathItem(ref=None, summary=None, description=None, get=None, put=None, post=Operation(tags=None, summary=None, description=None, externalDocs=None, operationId=None, parameters=None, requestBody=RequestBody(description=None, content={'application/json': MediaType(media_type_schema=PydanticSchema(allOf=None, anyOf=None, oneOf=None, schema_not=None, schema_if=None, then=None, schema_else=None, dependentSchemas=None, prefixItems=None, items=None, contains=None, properties=None, patternProperties=None, additionalProperties=None, propertyNames=None, unevaluatedItems=None, unevaluatedProperties=None, type=None, enum=None, const=None, multipleOf=None, maximum=None, exclusiveMaximum=None, minimum=None, exclusiveMinimum=None, maxLength=None, minLength=None, pattern=None, maxItems=None, minItems=None, uniqueItems=None, maxContains=None, minContains=None, maxProperties=None, minProperties=None, required=None, dependentRequired=None, schema_format=None, contentEncoding=None, contentMediaType=None, contentSchema=None, title=None, description=None, default=None, deprecated=None, readOnly=None, writeOnly=None, examples=None, discriminator=None, xml=None, externalDocs=None, example=None, schema_class=<class '__main__.DocumentPUTParameters'>), example=None, examples=None, encoding=None)}, required=False), responses={'200': Response(description='pong', headers=None, content=None, links=None)}, callbacks=None, deprecated=False, security=None, servers=None), delete=None, options=None, head=None, patch=None, trace=None, servers=None, parameters=None)}, webhooks=None, components=Components(schemas={}, responses=None, parameters=None, examples=None, requestBodies=None, headers=None, securitySchemes=None, links=None, callbacks=None, pathItems=None), security=None, tags=None, externalDocs=None)

manycoding avatar May 30 '22 15:05 manycoding