param icon indicating copy to clipboard operation
param copied to clipboard

Serializing Date parameters does not support allow_None

Open MarcSkovMadsen opened this issue 2 years ago • 3 comments

Param: 1.12.0

I'm trying to help a user that wants to implement the Pydantic getting started example using Param. https://discourse.holoviz.org/t/creating-an-optional-datetime-parameter-using-param/3147.

He asks how to implement signup_ts: Optional[datetime] = None. I think its not possible with the existing parameters as I get the below error.

$ python 'script.py'
Traceback (most recent call last):
  File "script.py", line 12, in <module>
    deserialized_data = User.param.deserialize_parameters(json_data)
  File "C:\repos\private\panel-ai\.venv\lib\site-packages\param\parameterized.py", line 2100, in deserialize_parameters
    return serializer.deserialize_parameters(self_or_cls, serialization, subset=subset)
  File "C:\repos\private\panel-ai\.venv\lib\site-packages\param\serializer.py", line 113, in deserialize_parameters
    deserialized = pobj.param[name].deserialize(value)
  File "C:\repos\private\panel-ai\.venv\lib\site-packages\param\__init__.py", line 1928, in deserialize
    return dt.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
TypeError: strptime() argument 1 must be str, not None
import param
import json

class User(param.Parameterized):
    signup_ts = param.Date(allow_None=True, doc="""The sign up time of the user""")


external_data = {
    'signup_ts': None,
}
json_data = json.dumps(external_data)
deserialized_data = User.param.deserialize_parameters(json_data)
User(**deserialized_data)

Additional Context

If you look at the Pydantic getting started example you will realize that its deserializing is much more flexible/ forgiving as it will be able to converts string to ints for integer parameters, not care so much about the date time format for datetime parameters etc.

MarcSkovMadsen avatar Dec 07 '21 17:12 MarcSkovMadsen

I've changed the title, because Date parameters do support allow_None:

>>> import param, json
>>> class User(param.Parameterized):
        signup_ts = param.Date(allow_None=True, doc="""The sign up time of the user""")
>>> u = User()
>>> print(u.signup_ts)
None

Your example above is specifically about serializing Date Parameters whose value is None, and it does look like there is an issue there. @jlstevens?

If you look at the Pydantic getting started example you will realize that its deserializing is much more flexible/ forgiving as it will be able to converts string to ints for integer parameters, not care so much about the date time format for datetime parameters etc.

Right. As https://github.com/samuelcolvin/pydantic/issues/578 says, Pydantic is a parsing library, not a validation library like Param. Pydantic is designed to ensure that usable values are extracted from what is provided by the user, while Param tries to give feedback to the user that what they provided is not suitable. E.g. sure, the user might have meant 3 when they put in the string " 3" or the float 3.14 for an integer, but are we sure? Should it also be 3 for "3..."? or "3 feet" or "three"? At some point you have to give up and stop making assumptions. Param gives up quickly, rejecting anything that's not clearly the right object, while Pydantic will bend over backwards to make it fit. At a downstream level, code with either approach can rest assured that only the indicated type will be provided, but Param takes the position that users need feedback when they do crazy things, not for the program to blindly go forward with potentially undetected issues.

Param offers a separate mechanism set_in_bounds() that is more forgiving, and we could expand that to be even more forgiving if that's useful, as long as we still catch errors when that's not used.

jbednar avatar Dec 14 '21 23:12 jbednar

I've not yet investigated deeply but the scheme should be fine as it is implemented like this which means the fix should be trivial None skip when serializing and deserializing dates. I'll make a PR shortly.

jlstevens avatar Dec 15 '21 10:12 jlstevens

BTW, I think the serialization support is a red herring for the specific task of comparison with Pydantic. I've added an equivalent to the Pydantic getting started example to https://discourse.holoviz.org/t/creating-an-optional-datetime-parameter-using-param/3147/10, which does not depend on serialization and does support None.

jbednar avatar Dec 15 '21 22:12 jbednar

@jlstevens can this issue be closed?

hoxbro avatar Oct 24 '22 15:10 hoxbro

Based on the merged PR, I think so...

jlstevens avatar Oct 24 '22 16:10 jlstevens