I'm trying to make a subclass of timedelta that expects to receive milliseconds instead of seconds, but it's not currently working.
Am I going against the grain? Is there a "right" way to achieve this with Pydantic? Or do I somehow need to tell Pydantic that MillisecondTimedelta
is just a timedelta
..
from datetime import timedelta
from pydantic import BaseModel
class MillisecondTimedelta(timedelta):
@classmethod
def __get_validators__(cls):
# timedelta expects seconds
yield lambda v: v / 1000
yield cls
class MyModel(BaseModel):
td: MillisecondTimedelta
data = {
"td": 7598040,
}
print(MyModel(**data))
Results in:
Traceback (most recent call last):
File "main.py", line 14, in <module>
class MyModel(BaseModel):
File "pydantic/main.py", line 262, in pydantic.main.ModelMetaclass.__new__
File "pydantic/fields.py", line 315, in pydantic.fields.ModelField.infer
File "pydantic/fields.py", line 284, in pydantic.fields.ModelField.__init__
File "pydantic/fields.py", line 362, in pydantic.fields.ModelField.prepare
File "pydantic/fields.py", line 541, in pydantic.fields.ModelField.populate_validators
File "pydantic/class_validators.py", line 255, in pydantic.class_validators.prep_validators
File "pydantic/class_validators.py", line 238, in pydantic.class_validators.make_generic_validator
File "/usr/lib/python3.8/inspect.py", line 3105, in signature
return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
File "/usr/lib/python3.8/inspect.py", line 2854, in from_callable
return _signature_from_callable(obj, sigcls=cls,
File "/usr/lib/python3.8/inspect.py", line 2384, in _signature_from_callable
raise ValueError(
ValueError: no signature found for builtin type <class '__main__.MillisecondTimedelta'>
Aha, turns out I needed to change 2 things.
Actually return a timedelta
from the validator, I was returning cls
which was my custom subclass.
Don't subclass timedelta
from datetime import timedelta
from pydantic import BaseModel
class MillisecondTimedelta:
@classmethod
def __get_validators__(cls):
yield lambda v: timedelta(milliseconds=v)
class MyModel(BaseModel):
td: MillisecondTimedelta
data = {
"td": 7598040,
}
print(repr(MyModel(**data)))
MyModel(td=datetime.timedelta(seconds=7598, microseconds=40000))