adds support for datetime serialization

This commit is contained in:
Mose Müller 2024-07-09 15:41:30 +02:00
parent 8afee54c51
commit cf0780b2ca
5 changed files with 58 additions and 5 deletions

View File

@ -1,16 +1,22 @@
import enum
import logging
from datetime import datetime
from typing import TYPE_CHECKING, Any, NoReturn, cast
import pydase
import pydase.components
import pydase.units as u
from pydase.utils.helpers import get_component_classes
from pydase.utils.serialization.types import SerializedObject
from pydase.utils.serialization.types import (
SerializedDatetime,
SerializedException,
SerializedObject,
)
if TYPE_CHECKING:
from collections.abc import Callable
logger = logging.getLogger(__name__)
@ -33,6 +39,7 @@ class Deserializer:
"dict": cls.deserialize_dict,
"method": cls.deserialize_method,
"Exception": cls.deserialize_exception,
"datetime": cls.deserialize_datetime,
}
# First go through handled types (as ColouredEnum is also within the components)
@ -57,6 +64,10 @@ class Deserializer:
def deserialize_quantity(cls, serialized_object: SerializedObject) -> Any:
return u.convert_to_quantity(serialized_object["value"]) # type: ignore
@classmethod
def deserialize_datetime(cls, serialized_object: SerializedDatetime) -> datetime:
return datetime.fromisoformat(serialized_object["value"])
@classmethod
def deserialize_enum(
cls,
@ -88,11 +99,11 @@ class Deserializer:
return
@classmethod
def deserialize_exception(cls, serialized_object: SerializedObject) -> NoReturn:
def deserialize_exception(cls, serialized_object: SerializedException) -> NoReturn:
import builtins
try:
exception = getattr(builtins, serialized_object["name"]) # type: ignore
exception = getattr(builtins, serialized_object["name"])
except AttributeError:
exception = type(serialized_object["name"], (Exception,), {}) # type: ignore
raise exception(serialized_object["value"])

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import inspect
import logging
import sys
from datetime import datetime
from enum import Enum
from typing import TYPE_CHECKING, Any, Literal, cast
@ -21,6 +22,7 @@ from pydase.utils.serialization.types import (
DataServiceTypes,
SerializedBool,
SerializedDataService,
SerializedDatetime,
SerializedDict,
SerializedEnum,
SerializedException,
@ -61,6 +63,9 @@ class Serializer:
if isinstance(obj, Exception):
result = cls._serialize_exception(obj)
elif isinstance(obj, datetime):
result = cls._serialize_datetime(obj, access_path=access_path)
elif isinstance(obj, AbstractDataService):
result = cls._serialize_data_service(obj, access_path=access_path)
@ -113,6 +118,16 @@ class Serializer:
"value": obj,
}
@classmethod
def _serialize_datetime(cls, obj: datetime, access_path: str) -> SerializedDatetime:
return {
"type": "datetime",
"value": str(obj),
"doc": None,
"full_access_path": access_path,
"readonly": True,
}
@classmethod
def _serialize_exception(cls, obj: Exception) -> SerializedException:
return {

View File

@ -45,6 +45,11 @@ class SerializedString(SerializedObjectBase):
type: Literal["str"]
class SerializedDatetime(SerializedObjectBase):
type: Literal["datetime"]
value: str
class SerializedEnum(SerializedObjectBase):
name: str
value: str
@ -107,6 +112,7 @@ SerializedObject = (
| SerializedFloat
| SerializedInteger
| SerializedString
| SerializedDatetime
| SerializedList
| SerializedDict
| SerializedNoneType

View File

@ -1,4 +1,5 @@
import enum
from datetime import datetime
from typing import Any
import pydase.components
@ -137,6 +138,16 @@ def test_loads_primitive_types(obj: Any, obj_serialization: SerializedObject) ->
"name": "MyService",
},
),
(
datetime.fromisoformat("2024-07-09 15:37:08.249845"),
{
"full_access_path": "",
"type": "datetime",
"value": "2024-07-09 15:37:08.249845",
"readonly": True,
"doc": None,
},
),
],
)
def test_loads_advanced_types(obj: Any, obj_serialization: SerializedObject) -> None:

View File

@ -1,5 +1,6 @@
import asyncio
import enum
from datetime import datetime
from enum import Enum
from typing import Any, ClassVar
@ -92,6 +93,16 @@ service_instance = ServiceClass()
"doc": None,
},
),
(
datetime.fromisoformat("2024-07-09 15:37:08.249845"),
{
"full_access_path": "",
"type": "datetime",
"value": "2024-07-09 15:37:08.249845",
"readonly": True,
"doc": None,
},
),
],
)
def test_dump(test_input: Any, expected: dict[str, Any]) -> None:
@ -476,8 +487,7 @@ def test_derived_data_service_serialization() -> None:
def name(self, value: str) -> None:
self._name = value
class DerivedService(BaseService):
...
class DerivedService(BaseService): ...
base_service_serialization = dump(BaseService())
derived_service_serialization = dump(DerivedService())