feat(inventory/store): init path_match utility

This commit is contained in:
Johannes Kirschbauer
2025-05-23 21:36:14 +02:00
parent 57cd50ae35
commit ed764a2f0f
2 changed files with 75 additions and 0 deletions

View File

@@ -9,6 +9,33 @@ from typing import Any
from clan_lib.errors import ClanError
def path_match(path: list[str], whitelist_paths: list[list[str]]) -> bool:
"""
Returns True if path matches any whitelist path with "*" wildcards.
I.e.:
whitelist_paths = [["a.b.*"]]
path = ["a", "b", "c"]
path_match(path, whitelist_paths) == True
whitelist_paths = ["a.b.c", "a.b.*"]
path = ["a", "b", "d"]
path_match(path, whitelist_paths) == False
"""
for wp in whitelist_paths:
if len(path) != len(wp):
continue
match = True
for p, w in zip(path, wp, strict=False):
if w != "*" and p != w:
match = False
break
if match:
return True
return False
def flatten_data(data: dict, parent_key: str = "", separator: str = ".") -> dict:
"""
Recursively flattens a nested dictionary structure where keys are joined by the separator.

View File

@@ -9,10 +9,58 @@ from clan_lib.persist.util import (
calc_patches,
delete_by_path,
determine_writeability,
path_match,
unmerge_lists,
)
@pytest.mark.parametrize(
("path", "whitelist", "expected"),
[
# Exact matches
(["a", "b", "c"], [["a", "b", "c"]], True),
(["a", "b"], [["a", "b"]], True),
([], [[]], True),
# Wildcard matches
(["a", "b", "c"], [["a", "*", "c"]], True),
(["a", "x", "c"], [["a", "*", "c"]], True),
(["a", "b", "c"], [["*", "b", "c"]], True),
(["a", "b", "c"], [["a", "b", "*"]], True),
(["a", "b", "c"], [["*", "*", "*"]], True),
# Multiple patterns - one matches
(["a", "b", "c"], [["x", "y", "z"], ["a", "*", "c"]], True),
(["x", "y", "z"], [["a", "*", "c"], ["x", "y", "z"]], True),
# Length mismatch
(["a", "b", "c"], [["a", "b"]], False),
(["a", "b"], [["a", "b", "c"]], False),
# Non-matching
(["a", "b", "c"], [["a", "b", "x"]], False),
(["a", "b", "c"], [["a", "x", "x"]], False),
(["a", "b", "c"], [["x", "x", "x"]], False),
# Empty whitelist
(["a"], [], False),
# Wildcards and exact mixed
(
["instances", "inst1", "roles", "roleA", "settings"],
[["instances", "*", "roles", "*", "settings"]],
True,
),
# Partial wildcard - length mismatch should fail
(
["instances", "inst1", "roles", "roleA"],
[["instances", "*", "roles", "*", "settings"]],
False,
),
# Empty path, no patterns
([], [], False),
],
)
def test_path_match(
path: list[str], whitelist: list[list[str]], expected: bool
) -> None:
assert path_match(path, whitelist) == expected
# --------- Patching tests ---------
def test_patch_nested() -> None:
orig = {"a": 1, "b": {"a": 2.1, "b": 2.2}, "c": 3}