Closed skewty closed 4 months ago
@skewty Hi,
The text of an empty element is parsed by the xml parser as None
, not as an empty string:
>>> import lxml.etree
>>> root = lxml.etree.fromstring('<root><element></element></root>')
>>> root.find('element').text is None
True
but in your case SenderName
is a non-optional string.
Therefore you should make it Optional:
class SenderName(RootXmlModel[Optional[str]], tag="name"):
root: Optional[str] = None
or set a default value if you desire it to be a string anyway:
class SenderName(RootXmlModel[str], tag="name"):
root: str = ''
Tried out your suggestion and came across this issue which was recently reported:
https://youtrack.jetbrains.com/issue/PY-70544/False-positive-UnionType-not-accepted-but-Optional-is.
Also, I see you are adding type hints to both the generic and root.
I saw, I believe in the docs, RootXmlModel being used without double typing as such:
class SenderName(RootXmlModel[Optional[str]], tag="name"):
pass
Is providing the type for root field necessary?
This did the trick and solves my issues / makes it through my unit tests:
class SenderName(RootXmlModel[str], tag="name"):
root: str = ''
class SenderDataDef(RootXmlModel, tag="senderdata"):
root: list[tuple[SenderAddress | None, SenderName | None, SenderLocation | None]]
def test_request_system_info_many_from_xml():
input_xml = Path("request-systeminfo-many.xml").read_bytes()
request = models.SystemInfoRequest.from_xml(input_xml)
assert len(request.sender_data) == 9
assert request.sender_data[0].address == "400"
assert request.sender_data[0].name == ""
assert request.sender_data[-1].address == "410"
assert request.sender_data[-1].name == "410"
output_xml = request.to_xml(skip_empty=False) # this must be false
assert request == models.SystemInfoRequest.from_xml(output_xml)
Big thanks!
I saw, I believe in the docs, RootXmlModel being used without double typing as such:
class SenderName(RootXmlModel[Optional[str]], tag="name"): pass
Is providing the type for root field necessary?
Yes, you have to provide a type for the root field, but you may omit it for the class itself to get rid of double typing. So this should work too:
class SenderName(RootXmlModel, tag="name"):
root: Optional[str] = None
This Code
Raises
Also Tried
I tried to use:
but it doesn't run until after the error above.
Any ideas? (I believe this is an lxml "feature")