Skip to content

Commit

Permalink
fix: we have a warning for every sub-variant
Browse files Browse the repository at this point in the history
Signed-off-by: Luka Peschke <mail@lukapeschke.com>
  • Loading branch information
lukapeschke committed Oct 31, 2024
1 parent 287b8c9 commit 51aaa25
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
10 changes: 3 additions & 7 deletions src/serializers/type_serializers/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,15 @@ fn to_python(
let mut new_extra = extra.clone();
new_extra.check = SerCheck::Strict;

let res = to_python_extractor(value, include, exclude, &new_extra, choices);

let errors = match res {
let errors = match to_python_extractor(value, include, exclude, &new_extra, choices) {
ToPythonExtractorResult::Success(obj) => return Ok(obj),
ToPythonExtractorResult::Errors(errs) => errs,
};

if retry_with_lax_check {
new_extra.check = SerCheck::Lax;
for comb_serializer in choices {
if let Ok(v) = comb_serializer.to_python(value, include, exclude, &new_extra) {
return Ok(v);
}
if let ToPythonExtractorResult::Success(v) = to_python_extractor(value, include, exclude, &new_extra, choices) {
return Ok(v);
}
}

Expand Down
33 changes: 33 additions & 0 deletions tests/serializers/test_union.py
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,11 @@ def __init__(self, type_: Literal['cat']) -> None:
self.type_ = 'cat'


class ModelAlien:
def __init__(self, type_: Literal['alien']) -> None:
self.type_ = 'alien'


@pytest.fixture
def model_a_b_union_schema() -> core_schema.UnionSchema:
return core_schema.union_schema(
Expand Down Expand Up @@ -850,6 +855,20 @@ def test_union_of_unions_of_models(model_a_b_union_schema: core_schema.UnionSche
assert s.to_python(ModelCat(type_='cat'), warnings='error') == {'type_': 'cat'}
assert s.to_python(ModelDog(type_='dog'), warnings='error') == {'type_': 'dog'}

# All warnings should be available
messages = [
'Expected `ModelA` but got `ModelAlien`',
'Expected `ModelB` but got `ModelAlien`',
'Expected `ModelCat` but got `ModelAlien`',
'Expected `ModelDog` but got `ModelAlien`',
]

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
s.to_python(ModelAlien(type_='alien'))
for m in messages:
assert m in str(w[0].message)


def test_union_of_unions_of_models_with_tagged_union(model_a_b_union_schema: core_schema.UnionSchema) -> None:
s = SchemaSerializer(
Expand Down Expand Up @@ -885,3 +904,17 @@ def test_union_of_unions_of_models_with_tagged_union(model_a_b_union_schema: cor
assert s.to_python(ModelB(c='c', d='d'), warnings='error') == {'c': 'c', 'd': 'd'}
assert s.to_python(ModelCat(type_='cat'), warnings='error') == {'type_': 'cat'}
assert s.to_python(ModelDog(type_='dog'), warnings='error') == {'type_': 'dog'}

# All warnings should be available
messages = [
'Expected `ModelA` but got `ModelAlien`',
'Expected `ModelB` but got `ModelAlien`',
'Expected `ModelCat` but got `ModelAlien`',
'Expected `ModelDog` but got `ModelAlien`',
]

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
s.to_python(ModelAlien(type_='alien'))
for m in messages:
assert m in str(w[0].message)

0 comments on commit 51aaa25

Please sign in to comment.