Skip to content

Extra allOf keys in translation of Unions to OpenAPI schema when Field is used #1209

@chriswmackey

Description

@chriswmackey

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

pydantic version: 1.4
            pydantic compiled: False
                 install path: C:\Users\chris\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\pydantic
               python version: 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:05:16) [MSC v.1915 32 bit (Intel)]
                     platform: Windows-10-10.0.18362-SP0
     optional deps. installed: []

Description

My teammates and I debated this for a bit but we're fairly confident that we're experiencing a bug, though it could just be a misunderstanding of how the translation to OpenAPI schema is intended to happen. We can at least say that we couldn't find any other issues on this github addressing it or samples in the docs about our case.

Specifically, when we run the following sample:

from pydantic import BaseModel, Field
from typing import Union
from pprint import pprint

class TestClassA(BaseModel):
    pass

class TestClassB(BaseModel):
    pass

class TestClassC(BaseModel):
    a: Union[TestClassA, TestClassB]

pprint(TestClassC.schema())

... we get the expected result:

{'definitions': {'TestClassA': {'properties': {},
                                'title': 'TestClassA',
                                'type': 'object'},
                 'TestClassB': {'properties': {},
                                'title': 'TestClassB',
                                'type': 'object'}},
 'properties': {'a': {'anyOf': [{'$ref': '#/definitions/TestClassA'},
                                {'$ref': '#/definitions/TestClassB'}],
                      'title': 'A'}},
 'required': ['a'],
 'title': 'TestClassC',
 'type': 'object'}

However, when we change TestClassC to be the following:

class TestClassC(BaseModel):
    a: Union[TestClassA, TestClassB] = Field(..., description='description...')

... we get the following:

{'definitions': {'TestClassA': {'properties': {},
                                'title': 'TestClassA',
                                'type': 'object'},
                 'TestClassB': {'properties': {},
                                'title': 'TestClassB',
                                'type': 'object'}},
 'properties': {'a': {'anyOf': [{'allOf': [{'$ref': '#/definitions/TestClassA'}]},
                                {'allOf': [{'$ref': '#/definitions/TestClassB'}]}],
                      'description': 'description...',
                      'title': 'A'}},
 'required': ['a'],
 'title': 'TestClassC',
 'type': 'object'}

Take particular note of the additional 'allOf' keys under the 'properties'

We get the same additional 'allOf' keys if we change TestClassC to be the following:

class TestClassC(BaseModel):
    a: Union[TestClassA, TestClassB] = TestClassA()

Right now, we're using a workaround with the schema_extra capability to get rid of these extra allOf keys but this seemed a bit hacky to us. If these allOf keys are the result of a bug, we're happy to provide more test cases that trigger it if that would help. Or, if there's a better way to get rid of it these extra keys that we overlooked, we're happy to help documenting it in any way that we can so others like us don't get confused. Thank you for taking the time to read this issue and for the incredibly useful package!

Metadata

Metadata

Assignees

Labels

bug V1Bug related to Pydantic V1.Xhelp wantedPull Request welcome

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions