Skip to content

Commit aac1069

Browse files
Fix regression in core schema generation for indirect definition references (#8702)
Co-authored-by: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com>
1 parent 43327d8 commit aac1069

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

pydantic/_internal/_core_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def _handle_ser_schemas(self, ser_schema: core_schema.SerSchema, f: Walk) -> cor
228228
def handle_definitions_schema(self, schema: core_schema.DefinitionsSchema, f: Walk) -> core_schema.CoreSchema:
229229
new_definitions: list[core_schema.CoreSchema] = []
230230
for definition in schema['definitions']:
231-
if 'schema_ref' and 'ref' in definition:
231+
if 'schema_ref' in definition and 'ref' in definition:
232232
# This indicates a purposely indirect reference
233233
# We want to keep such references around for implications related to JSON schema, etc.:
234234
new_definitions.append(definition)

tests/test_discriminated_union.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,3 +1763,91 @@ class CreateObjectDto(BaseModel):
17631763
'type': 'object',
17641764
},
17651765
}
1766+
1767+
1768+
def test_nested_discriminator() -> None:
1769+
"""
1770+
The exact details of the JSON schema produced are not necessarily important; the test was added in response to a
1771+
regression that caused the inner union to lose its discriminator. Even if the schema changes, the important
1772+
thing is that the core schema (and therefore JSON schema) produced has an actual discriminated union in it.
1773+
For more context, see: https://github.com/pydantic/pydantic/issues/8688.
1774+
"""
1775+
1776+
class Step_A(BaseModel):
1777+
type: Literal['stepA']
1778+
count: int
1779+
1780+
class Step_B(BaseModel):
1781+
type: Literal['stepB']
1782+
value: float
1783+
1784+
class MyModel(BaseModel):
1785+
type: Literal['mixed']
1786+
sub_models: List['SubModel']
1787+
steps: Union[Step_A, Step_B] = Field(
1788+
default=None,
1789+
discriminator='type',
1790+
)
1791+
1792+
class SubModel(MyModel):
1793+
type: Literal['mixed']
1794+
blending: float
1795+
1796+
MyModel.model_rebuild()
1797+
assert MyModel.model_json_schema() == {
1798+
'$defs': {
1799+
'Step_A': {
1800+
'properties': {
1801+
'count': {'title': 'Count', 'type': 'integer'},
1802+
'type': {'const': 'stepA', 'title': 'Type'},
1803+
},
1804+
'required': ['type', 'count'],
1805+
'title': 'Step_A',
1806+
'type': 'object',
1807+
},
1808+
'Step_B': {
1809+
'properties': {
1810+
'type': {'const': 'stepB', 'title': 'Type'},
1811+
'value': {'title': 'Value', 'type': 'number'},
1812+
},
1813+
'required': ['type', 'value'],
1814+
'title': 'Step_B',
1815+
'type': 'object',
1816+
},
1817+
'SubModel': {
1818+
'properties': {
1819+
'blending': {'title': 'Blending', 'type': 'number'},
1820+
'steps': {
1821+
'default': None,
1822+
'discriminator': {
1823+
'mapping': {'stepA': '#/$defs/Step_A', 'stepB': '#/$defs/Step_B'},
1824+
'propertyName': 'type',
1825+
},
1826+
'oneOf': [{'$ref': '#/$defs/Step_A'}, {'$ref': '#/$defs/Step_B'}],
1827+
'title': 'Steps',
1828+
},
1829+
'sub_models': {'items': {'$ref': '#/$defs/SubModel'}, 'title': 'Sub Models', 'type': 'array'},
1830+
'type': {'const': 'mixed', 'title': 'Type'},
1831+
},
1832+
'required': ['type', 'sub_models', 'blending'],
1833+
'title': 'SubModel',
1834+
'type': 'object',
1835+
},
1836+
},
1837+
'properties': {
1838+
'steps': {
1839+
'default': None,
1840+
'discriminator': {
1841+
'mapping': {'stepA': '#/$defs/Step_A', 'stepB': '#/$defs/Step_B'},
1842+
'propertyName': 'type',
1843+
},
1844+
'oneOf': [{'$ref': '#/$defs/Step_A'}, {'$ref': '#/$defs/Step_B'}],
1845+
'title': 'Steps',
1846+
},
1847+
'sub_models': {'items': {'$ref': '#/$defs/SubModel'}, 'title': 'Sub Models', 'type': 'array'},
1848+
'type': {'const': 'mixed', 'title': 'Type'},
1849+
},
1850+
'required': ['type', 'sub_models'],
1851+
'title': 'MyModel',
1852+
'type': 'object',
1853+
}

0 commit comments

Comments
 (0)