Newer
Older

Jeremy M Fee
committed
"""Configure pydantic to allow UTCDateTime attributes on models.
"""
from datetime import datetime
from typing import Any, Callable, Dict, List, Tuple, TypeVar, Union
from obspy import UTCDateTime
from pydantic.errors import PydanticValueError
import pydantic.json
import pydantic.schema
import pydantic.validators
# placeholder type for register_custom_pydantic_type method
CustomType = TypeVar("CustomType")
def register_custom_pydantic_type(
custom_type: CustomType,
encoder: Callable[[CustomType], Any],
json_schema: Dict,
parsers: List[Callable[[Any], CustomType]],
):
try:
if custom_type.__custom_pydantic_type__:
# already registered
return

Jeremy M Fee
committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
pass
# add encoder
pydantic.json.ENCODERS_BY_TYPE[custom_type] = encoder
# add openapi mapping
pydantic.schema.field_class_to_schema += ((custom_type, json_schema),)
# add validator
pydantic.validators._VALIDATORS.append((custom_type, parsers))
# mark as installed
custom_type.__custom_pydantic_type__ = True
class UTCDateTimeError(PydanticValueError):
msg_template = "invalid date-time format"
def format_utcdatetime(o: UTCDateTime) -> str:
return o.isoformat()
def parse_utcdatetime(
value: Union[datetime, float, int, str, UTCDateTime]
) -> UTCDateTime:
try:
return UTCDateTime(value)
except:
raise UTCDateTimeError()
register_custom_pydantic_type(
UTCDateTime,
encoder=format_utcdatetime,
json_schema={"type": "string", "format": "date-time"},
parsers=[parse_utcdatetime],
)