Skip to content

Commit 9bb0705

Browse files
authored
Merge pull request #166 from dapper91/dev
- union collection deserialization bug fixed.
2 parents e7f345a + 1dde289 commit 9bb0705

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Changelog
22
=========
33

4+
2.8.1 (2024-01-21)
5+
------------------
6+
7+
- union collection deserialization bug fixed. See https://github.com/dapper91/pydantic-xml/pull/165.
8+
9+
410
2.8.0 (2024-01-13)
511
------------------
612

pydantic_xml/element/element.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ def apply_snapshot(self, snapshot: 'XmlElement[Any]') -> None:
116116
Applies a snapshot to the current element.
117117
"""
118118

119+
@abc.abstractmethod
120+
def step_forward(self) -> None:
121+
"""
122+
Increment the current element index.
123+
"""
124+
119125
@abc.abstractmethod
120126
def to_native(self) -> Any:
121127
"""
@@ -305,6 +311,7 @@ def create_snapshot(self) -> 'XmlElement[NativeElement]':
305311
attributes=dict(self._state.attrib) if self._state.attrib is not None else None,
306312
elements=[element.create_snapshot() for element in self._state.elements],
307313
nsmap=dict(self._nsmap) if self._nsmap is not None else None,
314+
sourceline=self._sourceline,
308315
)
309316
element._state.next_element_idx = self._state.next_element_idx
310317

@@ -319,6 +326,9 @@ def apply_snapshot(self, snapshot: 'XmlElement[NativeElement]') -> None:
319326
self._state.elements = snapshot._state.elements
320327
self._state.next_element_idx = snapshot._state.next_element_idx
321328

329+
def step_forward(self) -> None:
330+
self._state.next_element_idx += 1
331+
322332
def is_empty(self) -> bool:
323333
if not self._state.text and not self._state.tail and not self._state.attrib and len(self._state.elements) == 0:
324334
return True

pydantic_xml/serializers/factories/union.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def deserialize(
117117
last_error = e
118118

119119
if last_error is not None:
120+
element.step_forward()
120121
raise last_error
121122

122123
return result

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pydantic-xml"
3-
version = "2.8.0"
3+
version = "2.8.1"
44
description = "pydantic xml extension"
55
authors = ["Dmitry Pershin <dapper1291@gmail.com>"]
66
license = "Unlicense"

tests/test_errors.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,50 @@ class TestModel(BaseXmlModel, tag='model'):
170170
},
171171
},
172172
]
173+
174+
175+
def test_models_union_errors():
176+
class TestSubModel1(BaseXmlModel, tag='submodel1'):
177+
data: int
178+
179+
class TestSubModel2(BaseXmlModel, tag='submodel2'):
180+
data: float
181+
182+
class TestModel(BaseXmlModel, tag='model'):
183+
submodel: List[Union[TestSubModel1, TestSubModel2]]
184+
185+
xml = '''
186+
<model>
187+
<submodel2>a</submodel2>
188+
<submodel1>b</submodel1>
189+
</model>
190+
'''
191+
192+
with pytest.raises(pd.ValidationError) as exc:
193+
TestModel.from_xml(xml)
194+
195+
err = exc.value
196+
assert err.title == 'TestModel'
197+
assert err.error_count() == 2
198+
assert err.errors() == [
199+
{
200+
'input': 'a',
201+
'loc': ('submodel', 0, 'data'),
202+
'msg': f'[line {fmt_sourceline(3)}]: Input should be a valid number, unable to parse string as a number',
203+
'type': 'float_parsing',
204+
'ctx': {
205+
'orig': 'Input should be a valid number, unable to parse string as a number',
206+
'sourceline': fmt_sourceline(3),
207+
},
208+
},
209+
{
210+
'input': 'b',
211+
'loc': ('submodel', 1, 'data'),
212+
'msg': f'[line {fmt_sourceline(4)}]: Input should be a valid integer, unable to parse string as an integer',
213+
'type': 'int_parsing',
214+
'ctx': {
215+
'orig': 'Input should be a valid integer, unable to parse string as an integer',
216+
'sourceline': fmt_sourceline(4),
217+
},
218+
},
219+
]

0 commit comments

Comments
 (0)