Closed jwfraustro closed 7 months ago
@jwfraustro Hi,
Thanks for your feedback!
Your solution can be improved using generics:
import datetime as dt
from typing import Optional, Generic, TypeVar
from pydantic_xml import BaseXmlModel, computed_attr, element
NillableType = TypeVar('NillableType')
class NillableElement(BaseXmlModel, Generic[NillableType], skip_empty=True, nsmap={"xsi": "http://www.w3.org/2001/XMLSchema-instance"}):
value: Optional[NillableType] = None
@computed_attr(name="nil", ns="xsi")
def nil(self) -> Optional[str]:
if self.value is None:
return "true"
else:
return None
class Job(BaseXmlModel):
start_time: NillableElement[dt.datetime] = element(tag="startTime")
in that case you don't lose the type hinting.
Your proposal with nillable=True
parameter sounds reasonable. I think it is not very difficult to implement.
I will try to implement it in the next release.
Thanks for the help!
And yes, a feature like that would be excellent! Looking forward to that release!
Hi,
First off, thanks for the excellent library, I'm a big fan!
I'm hoping you can help me with a pain point I'm having trying to represent
nillable
XML elements in a model. I've tried to represent these elements a few different ways, and have only found one satisfactory, but not ideal, solution.For a simple XSD definition like this:
I'd like to be able to instantiate a
Job
model with either astartTime
value orNone
.For example, consider:
The way we were able to achieve this was with a class that (simplified) looks like this:
However, this means we lose the type hinting for
start_time
as adatetime
object, and we have to access the value asjob.start_time.value
instead ofjob.start_time
.Another complicating issue, we have a custom datetime type with some extra validation logic, that inherits from
datetime.datetime
.Unfortunately, as you know, comparison between simple types and models isn't supported, so we have to do something like this:
Similiar issue as before (plus some others), but now we've got an ambiguity between needing to call
job.start_time.value
orjob.start_time.root
depending on whether the value has been set or not.And even more complicating, because we're storing some of these models in a cache, we often have to roundtrip
XML <-> Model <-> JSON
and it's quite a bit of headache.The ideal, but probably not possible, solution would be to pass a
nillable=True
argument to theelement
function, and have it handle something like this automatically...All of this to say, is there a better way to represent
nillable
XML elements in a model? I've been tearing my hair out trying to find a consistent way to do this, and I'm hoping you might have an idea.If it's useful, since it's open-source, you can see the models we're currently working on here: spacetelescope/vo-models
P.S. I featured your library in a talk I presented: Python TAP Implementation at MAST: Lessons Learned under "Serialization Woes" :) I'm really hoping more people start using this library, it's fantastic!