updates Serializer functions

- using parse_full_access_path instead of parse_keyed_attribute
- renames get_next_level_dict_by_key to get_container_item_by_key
- replaces ensure_exists and get_nested_value by get_or_create_item_in_container

This allows us to handle access paths like "dict_attr['key'][0].some_attr".
This commit is contained in:
Mose Müller
2024-04-25 16:49:22 +02:00
parent c75b203c3d
commit b29c86ac2c
2 changed files with 122 additions and 123 deletions

View File

@ -13,8 +13,8 @@ from pydase.utils.serialization.serializer import (
SerializationPathError,
SerializedObject,
dump,
get_container_item_by_key,
get_nested_dict_by_path,
get_next_level_dict_by_key,
serialized_dict_is_nested_object,
set_nested_value_by_path,
)
@ -27,6 +27,25 @@ class MyEnum(enum.Enum):
FINISHED = "finished"
class MySubclass(pydase.DataService):
attr3 = 1.0
list_attr: ClassVar[list[Any]] = [1.0, 1]
class ServiceClass(pydase.DataService):
attr1 = 1.0
attr2 = MySubclass()
enum_attr = MyEnum.RUNNING
attr_list: ClassVar[list[Any]] = [0, 1, MySubclass()]
dict_attr: ClassVar[dict[Any, Any]] = {"foo": 1.0}
def my_task(self) -> None:
pass
service_instance = ServiceClass()
@pytest.mark.parametrize(
"test_input, expected",
[
@ -468,27 +487,14 @@ def test_derived_data_service_serialization() -> None:
@pytest.fixture
def setup_dict() -> dict[str, Any]:
class MySubclass(pydase.DataService):
attr3 = 1.0
list_attr: ClassVar[list[Any]] = [1.0, 1]
class ServiceClass(pydase.DataService):
attr1 = 1.0
attr2 = MySubclass()
enum_attr = MyEnum.RUNNING
attr_list: ClassVar[list[Any]] = [0, 1, MySubclass()]
dict_attr: ClassVar[dict[Any, Any]] = {"foo": 1.0}
def my_task(self) -> None:
pass
return ServiceClass().serialize()["value"] # type: ignore
@pytest.mark.parametrize(
"attr_name, allow_append, expected",
"serialized_object, attr_name, allow_append, expected",
[
(
dump(service_instance)["value"],
"attr1",
False,
{
@ -500,18 +506,20 @@ def setup_dict() -> dict[str, Any]:
},
),
(
"attr_list[0]",
dump(service_instance.attr_list)["value"],
"[0]",
False,
{
"doc": None,
"full_access_path": "attr_list[0]",
"full_access_path": "[0]",
"readonly": False,
"type": "int",
"value": 0,
},
),
(
"attr_list[3]",
dump(service_instance.attr_list)["value"],
"[3]",
True,
{
# we do not know the full_access_path of this entry within the
@ -524,15 +532,17 @@ def setup_dict() -> dict[str, Any]:
},
),
(
"attr_list[3]",
dump(service_instance.attr_list)["value"],
"[3]",
False,
SerializationPathError,
),
(
"dict_attr['foo']",
dump(service_instance.dict_attr)["value"],
"['foo']",
False,
{
"full_access_path": 'dict_attr["foo"]',
"full_access_path": '["foo"]',
"value": 1.0,
"type": "float",
"doc": None,
@ -540,7 +550,8 @@ def setup_dict() -> dict[str, Any]:
},
),
(
"dict_attr['unset_key']",
dump(service_instance.dict_attr)["value"],
"['unset_key']",
True,
{
# we do not know the full_access_path of this entry within the
@ -553,11 +564,13 @@ def setup_dict() -> dict[str, Any]:
},
),
(
"dict_attr['unset_key']",
dump(service_instance.dict_attr)["value"],
"['unset_key']",
False,
SerializationPathError,
),
(
dump(service_instance)["value"],
"invalid_path",
True,
{
@ -571,32 +584,35 @@ def setup_dict() -> dict[str, Any]:
},
),
(
dump(service_instance)["value"],
"invalid_path",
False,
SerializationPathError,
),
# you should not be able to set an item of a thing that does not exist
(
'invalid_path["some_key"]',
True,
SerializationPathError,
),
(
"invalid_path[0]", # no way of knowing if that should be a dict / list
True,
SerializationPathError,
),
# # you should not be able to set an item of a thing that does not exist
# (
# 'invalid_path["some_key"]',
# True,
# SerializationPathError,
# ),
# (
# "invalid_path[0]", # no way of knowing if that should be a dict / list
# True,
# SerializationPathError,
# ),
],
)
def test_get_next_level_dict_by_key(
setup_dict: dict[str, Any], attr_name: str, allow_append: bool, expected: Any
def test_get_container_item_by_key(
serialized_object: dict[str, Any], attr_name: str, allow_append: bool, expected: Any
) -> None:
if isinstance(expected, type) and issubclass(expected, Exception):
with pytest.raises(expected):
get_next_level_dict_by_key(setup_dict, attr_name, allow_append=allow_append)
get_container_item_by_key(
serialized_object, attr_name, allow_append=allow_append
)
else:
nested_dict = get_next_level_dict_by_key(
setup_dict, attr_name, allow_append=allow_append
nested_dict = get_container_item_by_key(
serialized_object, attr_name, allow_append=allow_append
)
assert nested_dict == expected
@ -682,8 +698,8 @@ def test_update_invalid_list_index(
) -> None:
set_nested_value_by_path(setup_dict, "attr_list[10]", 30)
assert (
"Error occured trying to change 'attr_list[10]': list index "
"out of range" in caplog.text
"Error occured trying to change 'attr_list[10]': Index '10': list index out of "
"range" in caplog.text
)