mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-20 08:20:02 +02:00
Serializer adds full_access_path to serialized object representation
This commit is contained in:
parent
d9ea33abb6
commit
57e7deb552
@ -45,6 +45,7 @@ class DataServiceCache:
|
|||||||
)
|
)
|
||||||
except (SerializationPathError, SerializationValueError, KeyError):
|
except (SerializationPathError, SerializationValueError, KeyError):
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": full_access_path,
|
||||||
"value": None,
|
"value": None,
|
||||||
"type": None,
|
"type": None,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
|
@ -44,6 +44,7 @@ class SignatureDict(TypedDict):
|
|||||||
SerializedObject = TypedDict(
|
SerializedObject = TypedDict(
|
||||||
"SerializedObject",
|
"SerializedObject",
|
||||||
{
|
{
|
||||||
|
"full_access_path": str,
|
||||||
"name": NotRequired[str],
|
"name": NotRequired[str],
|
||||||
"value": "list[SerializedObject] | float | int | str | bool | dict[str, Any] | None", # noqa: E501
|
"value": "list[SerializedObject] | float | int | str | bool | dict[str, Any] | None", # noqa: E501
|
||||||
"type": str | None,
|
"type": str | None,
|
||||||
@ -59,28 +60,28 @@ SerializedObject = TypedDict(
|
|||||||
|
|
||||||
class Serializer:
|
class Serializer:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serialize_object(obj: Any) -> SerializedObject:
|
def serialize_object(obj: Any, access_path: str = "") -> SerializedObject:
|
||||||
result: SerializedObject
|
result: SerializedObject
|
||||||
if isinstance(obj, AbstractDataService):
|
if isinstance(obj, AbstractDataService):
|
||||||
result = Serializer._serialize_data_service(obj)
|
result = Serializer._serialize_data_service(obj, access_path=access_path)
|
||||||
|
|
||||||
elif isinstance(obj, list):
|
elif isinstance(obj, list):
|
||||||
result = Serializer._serialize_list(obj)
|
result = Serializer._serialize_list(obj, access_path=access_path)
|
||||||
|
|
||||||
elif isinstance(obj, dict):
|
elif isinstance(obj, dict):
|
||||||
result = Serializer._serialize_dict(obj)
|
result = Serializer._serialize_dict(obj, access_path=access_path)
|
||||||
|
|
||||||
# Special handling for u.Quantity
|
# Special handling for u.Quantity
|
||||||
elif isinstance(obj, u.Quantity):
|
elif isinstance(obj, u.Quantity):
|
||||||
result = Serializer._serialize_quantity(obj)
|
result = Serializer._serialize_quantity(obj, access_path=access_path)
|
||||||
|
|
||||||
# Handling for Enums
|
# Handling for Enums
|
||||||
elif isinstance(obj, Enum):
|
elif isinstance(obj, Enum):
|
||||||
result = Serializer._serialize_enum(obj)
|
result = Serializer._serialize_enum(obj, access_path=access_path)
|
||||||
|
|
||||||
# Methods and coroutines
|
# Methods and coroutines
|
||||||
elif inspect.isfunction(obj) or inspect.ismethod(obj):
|
elif inspect.isfunction(obj) or inspect.ismethod(obj):
|
||||||
result = Serializer._serialize_method(obj)
|
result = Serializer._serialize_method(obj, access_path=access_path)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
obj_type = type(obj).__name__
|
obj_type = type(obj).__name__
|
||||||
@ -88,6 +89,7 @@ class Serializer:
|
|||||||
readonly = False
|
readonly = False
|
||||||
doc = get_attribute_doc(obj)
|
doc = get_attribute_doc(obj)
|
||||||
result = {
|
result = {
|
||||||
|
"full_access_path": access_path,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
"readonly": readonly,
|
"readonly": readonly,
|
||||||
@ -97,7 +99,7 @@ class Serializer:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_enum(obj: Enum) -> SerializedObject:
|
def _serialize_enum(obj: Enum, access_path: str = "") -> SerializedObject:
|
||||||
import pydase.components.coloured_enum
|
import pydase.components.coloured_enum
|
||||||
|
|
||||||
value = obj.name
|
value = obj.name
|
||||||
@ -112,6 +114,7 @@ class Serializer:
|
|||||||
obj_type = "Enum"
|
obj_type = "Enum"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"name": class_name,
|
"name": class_name,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
@ -123,12 +126,13 @@ class Serializer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_quantity(obj: u.Quantity) -> SerializedObject:
|
def _serialize_quantity(obj: u.Quantity, access_path: str = "") -> SerializedObject:
|
||||||
obj_type = "Quantity"
|
obj_type = "Quantity"
|
||||||
readonly = False
|
readonly = False
|
||||||
doc = get_attribute_doc(obj)
|
doc = get_attribute_doc(obj)
|
||||||
value = {"magnitude": obj.m, "unit": str(obj.u)}
|
value = {"magnitude": obj.m, "unit": str(obj.u)}
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
"readonly": readonly,
|
"readonly": readonly,
|
||||||
@ -136,12 +140,16 @@ class Serializer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_dict(obj: dict[str, Any]) -> SerializedObject:
|
def _serialize_dict(obj: dict[str, Any], access_path: str = "") -> SerializedObject:
|
||||||
obj_type = "dict"
|
obj_type = "dict"
|
||||||
readonly = False
|
readonly = False
|
||||||
doc = get_attribute_doc(obj)
|
doc = get_attribute_doc(obj)
|
||||||
value = {key: Serializer.serialize_object(val) for key, val in obj.items()}
|
value = {
|
||||||
|
key: Serializer.serialize_object(val, access_path=f'{access_path}["{key}"]')
|
||||||
|
for key, val in obj.items()
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
"readonly": readonly,
|
"readonly": readonly,
|
||||||
@ -149,12 +157,16 @@ class Serializer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_list(obj: list[Any]) -> SerializedObject:
|
def _serialize_list(obj: list[Any], access_path: str = "") -> SerializedObject:
|
||||||
obj_type = "list"
|
obj_type = "list"
|
||||||
readonly = False
|
readonly = False
|
||||||
doc = get_attribute_doc(obj)
|
doc = get_attribute_doc(obj)
|
||||||
value = [Serializer.serialize_object(o) for o in obj]
|
value = [
|
||||||
|
Serializer.serialize_object(o, access_path=f"{access_path}[{i}]")
|
||||||
|
for i, o in enumerate(obj)
|
||||||
|
]
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
"readonly": readonly,
|
"readonly": readonly,
|
||||||
@ -162,7 +174,9 @@ class Serializer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_method(obj: Callable[..., Any]) -> SerializedObject:
|
def _serialize_method(
|
||||||
|
obj: Callable[..., Any], access_path: str = ""
|
||||||
|
) -> SerializedObject:
|
||||||
obj_type = "method"
|
obj_type = "method"
|
||||||
value = None
|
value = None
|
||||||
readonly = True
|
readonly = True
|
||||||
@ -176,12 +190,17 @@ class Serializer:
|
|||||||
signature: SignatureDict = {"parameters": {}, "return_annotation": {}}
|
signature: SignatureDict = {"parameters": {}, "return_annotation": {}}
|
||||||
|
|
||||||
for k, v in sig.parameters.items():
|
for k, v in sig.parameters.items():
|
||||||
|
default_value = cast(
|
||||||
|
dict[str, Any], {} if v.default == inspect._empty else dump(v.default)
|
||||||
|
)
|
||||||
|
default_value.pop("full_access_path", None)
|
||||||
signature["parameters"][k] = {
|
signature["parameters"][k] = {
|
||||||
"annotation": str(v.annotation),
|
"annotation": str(v.annotation),
|
||||||
"default": {} if v.default == inspect._empty else dump(v.default),
|
"default": default_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
"readonly": readonly,
|
"readonly": readonly,
|
||||||
@ -192,7 +211,9 @@ class Serializer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_data_service(obj: AbstractDataService) -> SerializedObject:
|
def _serialize_data_service(
|
||||||
|
obj: AbstractDataService, access_path: str = ""
|
||||||
|
) -> SerializedObject:
|
||||||
readonly = False
|
readonly = False
|
||||||
doc = get_attribute_doc(obj)
|
doc = get_attribute_doc(obj)
|
||||||
obj_type = "DataService"
|
obj_type = "DataService"
|
||||||
@ -231,7 +252,8 @@ class Serializer:
|
|||||||
|
|
||||||
val = getattr(obj, key)
|
val = getattr(obj, key)
|
||||||
|
|
||||||
value[key] = Serializer.serialize_object(val)
|
path = f"{access_path}.{key}" if access_path else key
|
||||||
|
value[key] = Serializer.serialize_object(val, access_path=path)
|
||||||
|
|
||||||
# If there's a running task for this method
|
# If there's a running task for this method
|
||||||
if key in obj._task_manager.tasks:
|
if key in obj._task_manager.tasks:
|
||||||
@ -244,6 +266,7 @@ class Serializer:
|
|||||||
value[key]["doc"] = get_attribute_doc(prop) # overwrite the doc
|
value[key]["doc"] = get_attribute_doc(prop) # overwrite the doc
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
"full_access_path": access_path,
|
||||||
"name": obj_name,
|
"name": obj_name,
|
||||||
"type": obj_type,
|
"type": obj_type,
|
||||||
"value": value,
|
"value": value,
|
||||||
@ -303,11 +326,10 @@ def set_nested_value_by_path(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
serialized_value = dump(value)
|
serialized_value = dump(value)
|
||||||
keys_to_keep = set(serialized_value.keys())
|
serialized_value["full_access_path"] = path
|
||||||
|
serialized_value["readonly"] = next_level_serialized_object["readonly"]
|
||||||
|
|
||||||
# TODO: you might also want to pop "doc" from serialized_value if
|
keys_to_keep = set(serialized_value.keys())
|
||||||
# it is overwriting the value of the current dict
|
|
||||||
serialized_value.pop("readonly") # type: ignore
|
|
||||||
|
|
||||||
next_level_serialized_object.update(serialized_value)
|
next_level_serialized_object.update(serialized_value)
|
||||||
|
|
||||||
@ -379,6 +401,7 @@ def get_next_level_dict_by_key(
|
|||||||
# Appending to list
|
# Appending to list
|
||||||
cast(list[SerializedObject], serialization_dict[attr_name]["value"]).append(
|
cast(list[SerializedObject], serialization_dict[attr_name]["value"]).append(
|
||||||
{
|
{
|
||||||
|
"full_access_path": "",
|
||||||
"value": None,
|
"value": None,
|
||||||
"type": None,
|
"type": None,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
|
@ -32,20 +32,24 @@ def test_image_serialization() -> None:
|
|||||||
self.my_image = pydase.components.Image()
|
self.my_image = pydase.components.Image()
|
||||||
|
|
||||||
assert dump(MyService()) == {
|
assert dump(MyService()) == {
|
||||||
|
"full_access_path": "",
|
||||||
"name": "MyService",
|
"name": "MyService",
|
||||||
"type": "DataService",
|
"type": "DataService",
|
||||||
"value": {
|
"value": {
|
||||||
"my_image": {
|
"my_image": {
|
||||||
|
"full_access_path": "my_image",
|
||||||
"name": "Image",
|
"name": "Image",
|
||||||
"type": "Image",
|
"type": "Image",
|
||||||
"value": {
|
"value": {
|
||||||
"format": {
|
"format": {
|
||||||
|
"full_access_path": "my_image.format",
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": "",
|
"value": "",
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
},
|
},
|
||||||
"load_from_base64": {
|
"load_from_base64": {
|
||||||
|
"full_access_path": "my_image.load_from_base64",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -72,6 +76,7 @@ def test_image_serialization() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
},
|
},
|
||||||
"load_from_matplotlib_figure": {
|
"load_from_matplotlib_figure": {
|
||||||
|
"full_access_path": "my_image.load_from_matplotlib_figure",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -95,6 +100,7 @@ def test_image_serialization() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
},
|
},
|
||||||
"load_from_path": {
|
"load_from_path": {
|
||||||
|
"full_access_path": "my_image.load_from_path",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -112,6 +118,7 @@ def test_image_serialization() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
},
|
},
|
||||||
"load_from_url": {
|
"load_from_url": {
|
||||||
|
"full_access_path": "my_image.load_from_url",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -126,6 +133,7 @@ def test_image_serialization() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
},
|
},
|
||||||
"value": {
|
"value": {
|
||||||
|
"full_access_path": "my_image.value",
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": "",
|
"value": "",
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
|
@ -30,12 +30,40 @@ class MyEnum(enum.Enum):
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"test_input, expected",
|
"test_input, expected",
|
||||||
[
|
[
|
||||||
(1, {"type": "int", "value": 1, "readonly": False, "doc": None}),
|
(
|
||||||
(1.0, {"type": "float", "value": 1.0, "readonly": False, "doc": None}),
|
1,
|
||||||
(True, {"type": "bool", "value": True, "readonly": False, "doc": None}),
|
{
|
||||||
|
"full_access_path": "",
|
||||||
|
"type": "int",
|
||||||
|
"value": 1,
|
||||||
|
"readonly": False,
|
||||||
|
"doc": None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1.0,
|
||||||
|
{
|
||||||
|
"full_access_path": "",
|
||||||
|
"type": "float",
|
||||||
|
"value": 1.0,
|
||||||
|
"readonly": False,
|
||||||
|
"doc": None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
True,
|
||||||
|
{
|
||||||
|
"full_access_path": "",
|
||||||
|
"type": "bool",
|
||||||
|
"value": True,
|
||||||
|
"readonly": False,
|
||||||
|
"doc": None,
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
u.Quantity(10, "m"),
|
u.Quantity(10, "m"),
|
||||||
{
|
{
|
||||||
|
"full_access_path": "",
|
||||||
"type": "Quantity",
|
"type": "Quantity",
|
||||||
"value": {"magnitude": 10, "unit": "meter"},
|
"value": {"magnitude": 10, "unit": "meter"},
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
@ -82,6 +110,7 @@ def test_enum_serialize() -> None:
|
|||||||
|
|
||||||
assert dump(EnumAttribute())["value"] == {
|
assert dump(EnumAttribute())["value"] == {
|
||||||
"some_enum": {
|
"some_enum": {
|
||||||
|
"full_access_path": "some_enum",
|
||||||
"type": "Enum",
|
"type": "Enum",
|
||||||
"name": "EnumClass",
|
"name": "EnumClass",
|
||||||
"value": "FOO",
|
"value": "FOO",
|
||||||
@ -92,6 +121,7 @@ def test_enum_serialize() -> None:
|
|||||||
}
|
}
|
||||||
assert dump(EnumPropertyWithoutSetter())["value"] == {
|
assert dump(EnumPropertyWithoutSetter())["value"] == {
|
||||||
"some_enum": {
|
"some_enum": {
|
||||||
|
"full_access_path": "some_enum",
|
||||||
"type": "Enum",
|
"type": "Enum",
|
||||||
"name": "EnumClass",
|
"name": "EnumClass",
|
||||||
"value": "FOO",
|
"value": "FOO",
|
||||||
@ -102,6 +132,7 @@ def test_enum_serialize() -> None:
|
|||||||
}
|
}
|
||||||
assert dump(EnumPropertyWithSetter())["value"] == {
|
assert dump(EnumPropertyWithSetter())["value"] == {
|
||||||
"some_enum": {
|
"some_enum": {
|
||||||
|
"full_access_path": "some_enum",
|
||||||
"type": "Enum",
|
"type": "Enum",
|
||||||
"name": "EnumClass",
|
"name": "EnumClass",
|
||||||
"value": "FOO",
|
"value": "FOO",
|
||||||
@ -125,6 +156,7 @@ def test_ColouredEnum_serialize() -> None:
|
|||||||
CANCELLED = "SlateGray"
|
CANCELLED = "SlateGray"
|
||||||
|
|
||||||
assert dump(Status.FAILED) == {
|
assert dump(Status.FAILED) == {
|
||||||
|
"full_access_path": "",
|
||||||
"type": "ColouredEnum",
|
"type": "ColouredEnum",
|
||||||
"name": "Status",
|
"name": "Status",
|
||||||
"value": "FAILED",
|
"value": "FAILED",
|
||||||
@ -157,6 +189,7 @@ async def test_method_serialization() -> None:
|
|||||||
|
|
||||||
assert dump(instance)["value"] == {
|
assert dump(instance)["value"] == {
|
||||||
"some_method": {
|
"some_method": {
|
||||||
|
"full_access_path": "some_method",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -166,6 +199,7 @@ async def test_method_serialization() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
},
|
},
|
||||||
"some_task": {
|
"some_task": {
|
||||||
|
"full_access_path": "some_task",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": TaskStatus.RUNNING.name,
|
"value": TaskStatus.RUNNING.name,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -191,6 +225,7 @@ def test_methods_with_type_hints() -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
assert dump(method_without_type_hint) == {
|
assert dump(method_without_type_hint) == {
|
||||||
|
"full_access_path": "",
|
||||||
"async": False,
|
"async": False,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"signature": {
|
"signature": {
|
||||||
@ -209,6 +244,7 @@ def test_methods_with_type_hints() -> None:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert dump(method_with_type_hint) == {
|
assert dump(method_with_type_hint) == {
|
||||||
|
"full_access_path": "",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -223,6 +259,7 @@ def test_methods_with_type_hints() -> None:
|
|||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
}
|
}
|
||||||
assert dump(method_with_union_type_hint) == {
|
assert dump(method_with_union_type_hint) == {
|
||||||
|
"full_access_path": "",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -249,6 +286,7 @@ def test_exposed_function_serialization() -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
assert dump(MyService().some_method) == {
|
assert dump(MyService().some_method) == {
|
||||||
|
"full_access_path": "",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -259,6 +297,7 @@ def test_exposed_function_serialization() -> None:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert dump(some_function) == {
|
assert dump(some_function) == {
|
||||||
|
"full_access_path": "",
|
||||||
"type": "method",
|
"type": "method",
|
||||||
"value": None,
|
"value": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
@ -286,30 +325,41 @@ def test_list_serialization() -> None:
|
|||||||
|
|
||||||
assert dump(instance)["value"] == {
|
assert dump(instance)["value"] == {
|
||||||
"list_attr": {
|
"list_attr": {
|
||||||
|
"full_access_path": "list_attr",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "list",
|
"type": "list",
|
||||||
"value": [
|
"value": [
|
||||||
{"doc": None, "readonly": False, "type": "int", "value": 1},
|
|
||||||
{
|
{
|
||||||
|
"full_access_path": "list_attr[0]",
|
||||||
|
"doc": None,
|
||||||
|
"readonly": False,
|
||||||
|
"type": "int",
|
||||||
|
"value": 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"full_access_path": "list_attr[1]",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "DataService",
|
"type": "DataService",
|
||||||
"name": "MySubclass",
|
"name": "MySubclass",
|
||||||
"value": {
|
"value": {
|
||||||
"bool_attr": {
|
"bool_attr": {
|
||||||
|
"full_access_path": "list_attr[1].bool_attr",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": True,
|
"value": True,
|
||||||
},
|
},
|
||||||
"int_attr": {
|
"int_attr": {
|
||||||
|
"full_access_path": "list_attr[1].int_attr",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
|
"full_access_path": "list_attr[1].name",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
"type": "str",
|
"type": "str",
|
||||||
@ -335,17 +385,20 @@ def test_dict_serialization() -> None:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert dump(test_dict) == {
|
assert dump(test_dict) == {
|
||||||
|
"full_access_path": "",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"value": {
|
"value": {
|
||||||
"DataService_key": {
|
"DataService_key": {
|
||||||
|
"full_access_path": '["DataService_key"]',
|
||||||
"name": "MyClass",
|
"name": "MyClass",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "DataService",
|
"type": "DataService",
|
||||||
"value": {
|
"value": {
|
||||||
"name": {
|
"name": {
|
||||||
|
"full_access_path": '["DataService_key"].name',
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "str",
|
"type": "str",
|
||||||
@ -354,19 +407,33 @@ def test_dict_serialization() -> None:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Quantity_key": {
|
"Quantity_key": {
|
||||||
|
"full_access_path": '["Quantity_key"]',
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "Quantity",
|
"type": "Quantity",
|
||||||
"value": {"magnitude": 1.0, "unit": "s"},
|
"value": {"magnitude": 1.0, "unit": "s"},
|
||||||
},
|
},
|
||||||
"bool_key": {"doc": None, "readonly": False, "type": "bool", "value": True},
|
"bool_key": {
|
||||||
|
"full_access_path": '["bool_key"]',
|
||||||
|
"doc": None,
|
||||||
|
"readonly": False,
|
||||||
|
"type": "bool",
|
||||||
|
"value": True,
|
||||||
|
},
|
||||||
"float_key": {
|
"float_key": {
|
||||||
|
"full_access_path": '["float_key"]',
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"value": 1.0,
|
"value": 1.0,
|
||||||
},
|
},
|
||||||
"int_key": {"doc": None, "readonly": False, "type": "int", "value": 1},
|
"int_key": {
|
||||||
|
"full_access_path": '["int_key"]',
|
||||||
|
"doc": None,
|
||||||
|
"readonly": False,
|
||||||
|
"type": "int",
|
||||||
|
"value": 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,8 +454,7 @@ def test_derived_data_service_serialization() -> None:
|
|||||||
def name(self, value: str) -> None:
|
def name(self, value: str) -> None:
|
||||||
self._name = value
|
self._name = value
|
||||||
|
|
||||||
class DerivedService(BaseService):
|
class DerivedService(BaseService): ...
|
||||||
...
|
|
||||||
|
|
||||||
base_service_serialization = dump(BaseService())
|
base_service_serialization = dump(BaseService())
|
||||||
derived_service_serialization = dump(DerivedService())
|
derived_service_serialization = dump(DerivedService())
|
||||||
@ -415,7 +481,7 @@ def setup_dict() -> dict[str, Any]:
|
|||||||
def my_task(self) -> None:
|
def my_task(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return ServiceClass().serialize()["value"]
|
return ServiceClass().serialize()["value"] # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def test_update_attribute(setup_dict: dict[str, Any]) -> None:
|
def test_update_attribute(setup_dict: dict[str, Any]) -> None:
|
||||||
@ -431,6 +497,7 @@ def test_update_nested_attribute(setup_dict: dict[str, Any]) -> None:
|
|||||||
def test_update_float_attribute_to_enum(setup_dict: dict[str, Any]) -> None:
|
def test_update_float_attribute_to_enum(setup_dict: dict[str, Any]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "attr2.attr3", MyEnum.RUNNING)
|
set_nested_value_by_path(setup_dict, "attr2.attr3", MyEnum.RUNNING)
|
||||||
assert setup_dict["attr2"]["value"]["attr3"] == {
|
assert setup_dict["attr2"]["value"]["attr3"] == {
|
||||||
|
"full_access_path": "attr2.attr3",
|
||||||
"name": "MyEnum",
|
"name": "MyEnum",
|
||||||
"doc": "MyEnum description",
|
"doc": "MyEnum description",
|
||||||
"enum": {"FINISHED": "finished", "RUNNING": "running"},
|
"enum": {"FINISHED": "finished", "RUNNING": "running"},
|
||||||
@ -443,6 +510,7 @@ def test_update_float_attribute_to_enum(setup_dict: dict[str, Any]) -> None:
|
|||||||
def test_update_enum_attribute_to_float(setup_dict: dict[str, Any]) -> None:
|
def test_update_enum_attribute_to_float(setup_dict: dict[str, Any]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "enum_attr", 1.01)
|
set_nested_value_by_path(setup_dict, "enum_attr", 1.01)
|
||||||
assert setup_dict["enum_attr"] == {
|
assert setup_dict["enum_attr"] == {
|
||||||
|
"full_access_path": "enum_attr",
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"readonly": False,
|
"readonly": False,
|
||||||
"type": "float",
|
"type": "float",
|
||||||
@ -452,6 +520,7 @@ def test_update_enum_attribute_to_float(setup_dict: dict[str, Any]) -> None:
|
|||||||
|
|
||||||
def test_update_task_state(setup_dict: dict[str, Any]) -> None:
|
def test_update_task_state(setup_dict: dict[str, Any]) -> None:
|
||||||
assert setup_dict["my_task"] == {
|
assert setup_dict["my_task"] == {
|
||||||
|
"full_access_path": "my_task",
|
||||||
"async": False,
|
"async": False,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
@ -462,6 +531,7 @@ def test_update_task_state(setup_dict: dict[str, Any]) -> None:
|
|||||||
}
|
}
|
||||||
set_nested_value_by_path(setup_dict, "my_task", TaskStatus.RUNNING)
|
set_nested_value_by_path(setup_dict, "my_task", TaskStatus.RUNNING)
|
||||||
assert setup_dict["my_task"] == {
|
assert setup_dict["my_task"] == {
|
||||||
|
"full_access_path": "my_task",
|
||||||
"async": False,
|
"async": False,
|
||||||
"doc": None,
|
"doc": None,
|
||||||
"frontend_render": False,
|
"frontend_render": False,
|
||||||
@ -474,12 +544,13 @@ def test_update_task_state(setup_dict: dict[str, Any]) -> None:
|
|||||||
|
|
||||||
def test_update_list_entry(setup_dict: dict[str, SerializedObject]) -> None:
|
def test_update_list_entry(setup_dict: dict[str, SerializedObject]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "attr_list[1]", 20)
|
set_nested_value_by_path(setup_dict, "attr_list[1]", 20)
|
||||||
assert setup_dict["attr_list"]["value"][1]["value"] == 20
|
assert setup_dict["attr_list"]["value"][1]["value"] == 20 # type: ignore # noqa
|
||||||
|
|
||||||
|
|
||||||
def test_update_list_append(setup_dict: dict[str, SerializedObject]) -> None:
|
def test_update_list_append(setup_dict: dict[str, SerializedObject]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "attr_list[3]", MyEnum.RUNNING)
|
set_nested_value_by_path(setup_dict, "attr_list[3]", MyEnum.RUNNING)
|
||||||
assert setup_dict["attr_list"]["value"][3] == {
|
assert setup_dict["attr_list"]["value"][3] == { # type: ignore
|
||||||
|
"full_access_path": "attr_list[3]",
|
||||||
"doc": "MyEnum description",
|
"doc": "MyEnum description",
|
||||||
"name": "MyEnum",
|
"name": "MyEnum",
|
||||||
"enum": {"FINISHED": "finished", "RUNNING": "running"},
|
"enum": {"FINISHED": "finished", "RUNNING": "running"},
|
||||||
@ -512,12 +583,12 @@ def test_update_invalid_path(
|
|||||||
|
|
||||||
def test_update_list_inside_class(setup_dict: dict[str, Any]) -> None:
|
def test_update_list_inside_class(setup_dict: dict[str, Any]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "attr2.list_attr[1]", 40)
|
set_nested_value_by_path(setup_dict, "attr2.list_attr[1]", 40)
|
||||||
assert setup_dict["attr2"]["value"]["list_attr"]["value"][1]["value"] == 40
|
assert setup_dict["attr2"]["value"]["list_attr"]["value"][1]["value"] == 40 # noqa
|
||||||
|
|
||||||
|
|
||||||
def test_update_class_attribute_inside_list(setup_dict: dict[str, Any]) -> None:
|
def test_update_class_attribute_inside_list(setup_dict: dict[str, Any]) -> None:
|
||||||
set_nested_value_by_path(setup_dict, "attr_list[2].attr3", 50)
|
set_nested_value_by_path(setup_dict, "attr_list[2].attr3", 50)
|
||||||
assert setup_dict["attr_list"]["value"][2]["value"]["attr3"]["value"] == 50
|
assert setup_dict["attr_list"]["value"][2]["value"]["attr3"]["value"] == 50 # noqa
|
||||||
|
|
||||||
|
|
||||||
def test_get_next_level_attribute_nested_dict(setup_dict: dict[str, Any]) -> None:
|
def test_get_next_level_attribute_nested_dict(setup_dict: dict[str, Any]) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user