Skip to content

Commit

Permalink
Support subclasses in lists in Union of List types (#1039)
Browse files Browse the repository at this point in the history
  • Loading branch information
sydney-runkle committed Oct 30, 2023
1 parent 866eb2d commit dd75669
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/serializers/type_serializers/list.rs
Expand Up @@ -116,4 +116,8 @@ impl TypeSerializer for ListSerializer {
fn get_name(&self) -> &str {
&self.name
}

fn retry_with_lax_check(&self) -> bool {
self.item_serializer.retry_with_lax_check()
}
}
3 changes: 2 additions & 1 deletion src/serializers/type_serializers/union.rs
Expand Up @@ -75,9 +75,10 @@ impl TypeSerializer for UnionSerializer {
exclude: Option<&PyAny>,
extra: &Extra,
) -> PyResult<PyObject> {
// try the serializers in with error_on fallback=true
// try the serializers in left to right order with error_on fallback=true
let mut new_extra = extra.clone();
new_extra.check = SerCheck::Strict;

for comb_serializer in &self.choices {
match comb_serializer.to_python(value, include, exclude, &new_extra) {
Ok(v) => return Ok(v),
Expand Down
56 changes: 56 additions & 0 deletions tests/serializers/test_union.py
Expand Up @@ -454,3 +454,59 @@ class Item(BaseModel):
)

assert s.to_python(DBUser(name='John', password='secret')) == {'name': 'John'}


def test_union_serializes_list_of_model_subclass_from_definition() -> None:
class BaseModel:
__slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__'

def __init__(self, **kwargs: Any):
for key, value in kwargs.items():
setattr(self, key, value)

class User(BaseModel):
name: str

class DBUser(User):
password: str
__pydantic_serializer__: ClassVar[SchemaSerializer]

DBUser.__pydantic_serializer__ = SchemaSerializer(
core_schema.model_schema(
DBUser,
core_schema.model_fields_schema(
{
'name': core_schema.model_field(core_schema.str_schema()),
'password': core_schema.model_field(core_schema.str_schema()),
}
),
)
)

class Item(BaseModel):
price: float

s = SchemaSerializer(
core_schema.definitions_schema(
core_schema.union_schema(
[
core_schema.list_schema(core_schema.definition_reference_schema('User'), strict=False),
core_schema.list_schema(core_schema.definition_reference_schema('Item'), strict=False),
]
),
[
core_schema.model_schema(
User,
core_schema.model_fields_schema({'name': core_schema.model_field(core_schema.str_schema())}),
ref='User',
),
core_schema.model_schema(
Item,
core_schema.model_fields_schema({'price': core_schema.model_field(core_schema.float_schema())}),
ref='Item',
),
],
)
)

assert s.to_python([DBUser(name='John', password='secret')]) == [{'name': 'John'}]

0 comments on commit dd75669

Please sign in to comment.