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

Fix schema-building bug with TypeAliasType for types with refs #8526

Merged
merged 1 commit into from Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions pydantic/_internal/_core_utils.py
Expand Up @@ -228,6 +228,14 @@ def _handle_ser_schemas(self, ser_schema: core_schema.SerSchema, f: Walk) -> cor
def handle_definitions_schema(self, schema: core_schema.DefinitionsSchema, f: Walk) -> core_schema.CoreSchema:
new_definitions: list[core_schema.CoreSchema] = []
for definition in schema['definitions']:
if 'schema_ref' and 'ref' in definition:
# This indicates a purposely indirect reference
# We want to keep such references around for implications related to JSON schema, etc.:
new_definitions.append(definition)
# However, we still need to walk the referenced definition:
self.walk(definition, f)
continue

updated_definition = self.walk(definition, f)
if 'ref' in updated_definition:
# If the updated definition schema doesn't have a 'ref', it shouldn't go in the definitions
Expand Down
24 changes: 23 additions & 1 deletion tests/test_type_alias_type.py
Expand Up @@ -4,7 +4,7 @@

import pytest
from annotated_types import MaxLen
from typing_extensions import Annotated, TypeAliasType
from typing_extensions import Annotated, Literal, TypeAliasType

from pydantic import BaseModel, Field, ValidationError
from pydantic.type_adapter import TypeAdapter
Expand Down Expand Up @@ -366,3 +366,25 @@ class MyOuterModel(BaseModel):

data = {'inner': {'x': 'hello'}, 'y': 1}
assert MyOuterModel.model_validate(data).model_dump() == data


def test_type_alias_to_type_with_ref():
class Div(BaseModel):
type: Literal['Div'] = 'Div'
components: List['AnyComponent']

AnyComponent = TypeAliasType('AnyComponent', Div)

adapter = TypeAdapter(AnyComponent)
adapter.validate_python({'type': 'Div', 'components': [{'type': 'Div', 'components': []}]})
with pytest.raises(ValidationError) as exc_info:
adapter.validate_python({'type': 'Div', 'components': [{'type': 'NotDiv', 'components': []}]})
assert exc_info.value.errors(include_url=False) == [
{
'ctx': {'expected': "'Div'"},
'input': 'NotDiv',
'loc': ('components', 0, 'type'),
'msg': "Input should be 'Div'",
'type': 'literal_error',
}
]