updates generate_serialized_data_paths to handle dictionaries well

This commit is contained in:
Mose Müller 2024-04-30 09:24:01 +02:00
parent 1c1584c2cf
commit b9131c9df2

View File

@ -468,50 +468,82 @@ def get_container_item_by_key(
raise SerializationPathError(f"Key '{processed_key}': {e}") raise SerializationPathError(f"Key '{processed_key}': {e}")
def generate_serialized_data_paths( def get_data_paths_from_serialized_object( # noqa: C901
data: dict[str, Any], parent_path: str = "" serialized_obj: SerializedObject,
parent_path: str = "",
) -> list[str]: ) -> list[str]:
""" """
Generate a list of access paths for all attributes in a dictionary representing Recursively extracts full access paths from a serialized object.
data serialized with `pydase.utils.serializer.Serializer`, excluding those that are
methods. This function handles nested structures, including lists, by generating
paths for each element in the nested lists.
Args: Args:
data (dict[str, Any]): The dictionary representing serialized data, typically serialized_obj (SerializedObject):
produced by `pydase.utils.serializer.Serializer`. The dictionary representing the serialization of an object. Produced by
parent_path (str, optional): The base path to prepend to the keys in the `data` `pydase.utils.serializer.Serializer`.
dictionary to form the access paths. Defaults to an empty string.
Returns: Returns:
list[str]: A list of strings where each string is a dot-notation access path list[str]:
to an attribute in the serialized data. For list elements, the path includes A list of strings, each representing a full access path in the serialized
the index in square brackets. object.
""" """
paths: list[str] = [] paths: list[str] = []
for key, value in data.items():
new_path = f"{parent_path}.{key}" if parent_path else key if isinstance(serialized_obj["value"], list):
for index, value in enumerate(serialized_obj["value"]):
new_path = f"{parent_path}[{index}]"
paths.append(new_path) paths.append(new_path)
if serialized_dict_is_nested_object(value): if serialized_dict_is_nested_object(value):
if isinstance(value["value"], list): paths.extend(get_data_paths_from_serialized_object(value, new_path))
for index, item in enumerate(value["value"]):
indexed_key_path = f"{new_path}[{index}]" elif serialized_dict_is_nested_object(serialized_obj):
paths.append(indexed_key_path) for key, value in cast(
if serialized_dict_is_nested_object(item): dict[str, SerializedObject], serialized_obj["value"]
paths.extend( ).items():
generate_serialized_data_paths( # Serialized dictionaries need to have a different new_path than nested
item["value"], indexed_key_path # classes
) if serialized_obj["type"] == "dict":
) processed_key = key
continue if isinstance(key, str):
# TODO: add dict? processed_key = f'"{key}"'
paths.extend(generate_serialized_data_paths(value["value"], new_path)) new_path = f"{parent_path}[{processed_key}]"
else:
new_path = f"{parent_path}.{key}" if parent_path != "" else key
paths.append(new_path)
if serialized_dict_is_nested_object(value):
paths.extend(get_data_paths_from_serialized_object(value, new_path))
return paths
def generate_serialized_data_paths(
data: dict[str, SerializedObject],
) -> list[str]:
"""
Recursively extracts full access paths from a serialized DataService class instance.
Args:
data (dict[str, SerializedObject]):
The value of the "value" key of a serialized DataService class instance.
Returns:
list[str]:
A list of strings, each representing a full access path in the serialized
object.
"""
paths: list[str] = []
for key, value in data.items():
paths.append(key)
if serialized_dict_is_nested_object(value):
paths.extend(get_data_paths_from_serialized_object(value, key))
return paths return paths
def serialized_dict_is_nested_object(serialized_dict: SerializedObject) -> bool: def serialized_dict_is_nested_object(serialized_dict: SerializedObject) -> bool:
return ( value = serialized_dict["value"]
serialized_dict["type"] != "Quantity" # We are excluding Quantity here as the value corresponding to the "value" key is
and isinstance(serialized_dict["value"], dict) # a dictionary of the form {"magnitude": ..., "unit": ...}
) or isinstance(serialized_dict["value"], list) return serialized_dict["type"] != "Quantity" and (isinstance(value, dict | list))