Skip to content

Commit

Permalink
Tweak ordering of definitions in generated schemas (#8583)
Browse files Browse the repository at this point in the history
  • Loading branch information
StrawHatDrag0n committed Jan 20, 2024
1 parent 5d6840f commit b2aa36a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
2 changes: 2 additions & 0 deletions pydantic/_internal/_generate_schema.py
Expand Up @@ -437,6 +437,8 @@ def clean_schema(self, schema: CoreSchema) -> CoreSchema:
if collect_invalid_schemas(schema):
raise self.CollectedInvalid()
schema = validate_core_schema(schema)
if 'definitions' in schema:
schema['definitions'] = list(reversed(schema['definitions']))
return schema

def collect_definitions(self, schema: CoreSchema) -> CoreSchema:
Expand Down
69 changes: 68 additions & 1 deletion tests/test_discriminated_union.py
Expand Up @@ -2,7 +2,7 @@
import sys
from enum import Enum, IntEnum
from types import SimpleNamespace
from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, Union
from typing import Any, Callable, Generic, List, Optional, Sequence, TypeVar, Union

import pytest
from dirty_equals import HasRepr, IsStr
Expand All @@ -12,6 +12,8 @@
from pydantic import BaseModel, ConfigDict, Discriminator, Field, TypeAdapter, ValidationError, field_validator
from pydantic._internal._discriminated_union import apply_discriminator
from pydantic.errors import PydanticUserError
from pydantic.fields import FieldInfo
from pydantic.json_schema import GenerateJsonSchema
from pydantic.types import Tag


Expand Down Expand Up @@ -1696,3 +1698,68 @@ class DiscriminatedModel(BaseModel):
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'


def test_presence_of_discriminator_when_generating_type_adaptor_json_schema_definitions() -> None:
class ItemType(str, Enum):
ITEM1 = 'item1'
ITEM2 = 'item2'

class CreateItem1(BaseModel):
item_type: Annotated[Literal[ItemType.ITEM1], Field(alias='type')]
id: int

class CreateItem2(BaseModel):
item_type: Annotated[Literal[ItemType.ITEM2], Field(alias='type')]
id: int

class CreateObjectDto(BaseModel):
id: int
items: List[
Annotated[
Union[
CreateItem1,
CreateItem2,
],
Field(discriminator='item_type'),
]
]

adaptor = TypeAdapter(
Annotated[CreateObjectDto, FieldInfo(examples=[{'id': 1, 'items': [{'id': 3, 'type': 'ITEM1'}]}])]
)

schema_map, definitions = GenerateJsonSchema().generate_definitions([(adaptor, 'validation', adaptor.core_schema)])
assert definitions == {
'CreateItem1': {
'properties': {'id': {'title': 'Id', 'type': 'integer'}, 'type': {'const': 'item1', 'title': 'Type'}},
'required': ['type', 'id'],
'title': 'CreateItem1',
'type': 'object',
},
'CreateItem2': {
'properties': {'id': {'title': 'Id', 'type': 'integer'}, 'type': {'const': 'item2', 'title': 'Type'}},
'required': ['type', 'id'],
'title': 'CreateItem2',
'type': 'object',
},
'CreateObjectDto': {
'properties': {
'id': {'title': 'Id', 'type': 'integer'},
'items': {
'items': {
'discriminator': {
'mapping': {'item1': '#/$defs/CreateItem1', 'item2': '#/$defs/CreateItem2'},
'propertyName': 'type',
},
'oneOf': [{'$ref': '#/$defs/CreateItem1'}, {'$ref': '#/$defs/CreateItem2'}],
},
'title': 'Items',
'type': 'array',
},
},
'required': ['id', 'items'],
'title': 'CreateObjectDto',
'type': 'object',
},
}

0 comments on commit b2aa36a

Please sign in to comment.