clan_lib: use flatten_data_structured

This commit is contained in:
Johannes Kirschbauer
2025-09-19 18:17:45 +02:00
parent 4ec3043a4e
commit 7e1b7b056d
2 changed files with 30 additions and 21 deletions

View File

@@ -3,10 +3,21 @@ from typing import Any
from clan_lib.persist.util import flatten_data, list_difference
def flatten_data_structured(data: dict, parent_path: tuple = ()) -> dict:
"""Flatten using tuple keys instead of string concatenation
def flatten_data_structured(data: dict, parent_path: tuple = ()) -> dict[tuple[str, ...], Any]:
"""Flatten data using tuple keys instead of string concatenation.
This eliminates ambiguity between literal dots in keys vs nested structure.
Avoids ambiguity issues with keys that contain dots or other separators.
Args:
data: The nested dictionary to flatten
parent_path: Current path as tuple (used for recursion)
Returns:
Dict with tuple keys representing the full path to each value
Example:
{"key.foo": "val1", "key": {"foo": "val2"}}
becomes:
{("key.foo",): "val1", ("key", "foo"): "val2"}
"""
flattened = {}
@@ -25,14 +36,14 @@ def flatten_data_structured(data: dict, parent_path: tuple = ()) -> dict:
def calculate_static_data(
all_values: dict[str, Any], persisted: dict[str, Any]
) -> dict[str, Any]:
) -> dict[tuple[str, ...], Any]:
"""Calculate the static (read-only) data by finding what exists in all_values
but not in persisted data.
This gives us a clear view of what cannot be modified/deleted.
"""
all_flat = flatten_data(all_values)
persisted_flat = flatten_data(persisted)
all_flat = flatten_data_structured(all_values)
persisted_flat = flatten_data_structured(persisted)
static_flat = {}
for key, value in all_flat.items():

View File

@@ -86,9 +86,9 @@ def test_calculate_static_data_basic() -> None:
}
expected_static = {
"settings.optionB": False,
"settings.listSetting": [1, 4],
"staticOnly": "staticValue",
("settings", "optionB"): False,
("settings","listSetting"): [1, 4],
("staticOnly",): "staticValue"
}
static_data = calculate_static_data(all_values, persisted)
@@ -132,11 +132,11 @@ def test_calculate_static_data_all_static() -> None:
persisted: dict = {}
expected_static = {
"name": "example",
"version": 1,
"settings.optionA": True,
"settings.listSetting": [1, 2, 3],
"staticOnly": "staticValue",
("name",): "example",
("version",): 1,
("settings", "optionA"): True,
("settings", "listSetting"): [1, 2, 3],
("staticOnly",): "staticValue",
}
static_data = calculate_static_data(all_values, persisted)
@@ -178,9 +178,9 @@ def test_calculate_nested_dicts() -> None:
}
expected_static = {
"level1.level2.staticKey": "staticValue",
"level1.anotherStatic": 42,
"topLevelStatic": True,
("level1", "level2", "staticKey"): "staticValue",
("level1", "anotherStatic"): 42,
("topLevelStatic",): True,
}
static_data = calculate_static_data(all_values, persisted)
@@ -188,9 +188,6 @@ def test_calculate_nested_dicts() -> None:
def test_dot_in_keys() -> None:
# TODO: This is a bug in the current implementation.
# We need to change the key representation to handle this case correctly.
# For now, we just document the behavior with this test.
all_values = {
"key.foo": "staticValue",
"key": {
@@ -200,7 +197,8 @@ def test_dot_in_keys() -> None:
persisted: dict = {}
expected_static = {
"key.foo": "anotherStaticValue",
("key.foo",): "staticValue",
("key", "foo"): "anotherStaticValue",
}
static_data = calculate_static_data(all_values, persisted)