creates functions to split full access paths and combine the atomic parts back together

This commit is contained in:
Mose Müller 2024-04-25 16:30:20 +02:00
parent 036e80b920
commit c75b203c3d
2 changed files with 91 additions and 0 deletions

View File

@ -1,5 +1,6 @@
import inspect import inspect
import logging import logging
import re
from collections.abc import Callable from collections.abc import Callable
from itertools import chain from itertools import chain
from typing import Any from typing import Any
@ -7,6 +8,52 @@ from typing import Any
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def parse_full_access_path(path: str) -> list[str]:
"""
Splits a full access path into its atomic parts, separating attribute names, numeric
indices, and string keys within indices.
The reverse function is given by `get_path_from_path_parts`.
Args:
path: str
The full access path string to be split into components.
Returns:
list[str]
A list of components that make up the path, including attribute names,
numeric indices, and string keys as separate elements.
"""
# <word_with_underscore> | [<any number of digits>]
# | ["<anything except ">"]
# | ['<anything except '>']
pattern = r'\w+|\[\d+\]|\["[^"]*"\]|\[\'[^\']*\']'
return re.findall(pattern, path)
def get_path_from_path_parts(path_parts: list[str]) -> str:
"""Creates the full access path from its atomic parts.
The reverse function is given by `parse_full_access_path`.
Args:
path_parts: list[str]
A list of components that make up the path, including attribute names,
numeric indices and string keys enclosed in square brackets as separate
elements.
Returns:
str
The full access path corresponding to the path_parts.
"""
path = ""
for path_part in path_parts:
if not path_part.startswith("[") and path != "":
path += "."
path += path_part
return path
def get_attribute_doc(attr: Any) -> str | None: def get_attribute_doc(attr: Any) -> str | None:
"""This function takes an input attribute attr and returns its documentation """This function takes an input attribute attr and returns its documentation
string if it's different from the documentation of its type, otherwise, string if it's different from the documentation of its type, otherwise,

View File

@ -4,11 +4,55 @@ import pydase
import pytest import pytest
from pydase.utils.helpers import ( from pydase.utils.helpers import (
get_object_attr_from_path, get_object_attr_from_path,
get_path_from_path_parts,
is_property_attribute, is_property_attribute,
parse_full_access_path,
parse_keyed_attribute, parse_keyed_attribute,
) )
@pytest.mark.parametrize(
"full_access_path, expected",
[
("attr_name", ["attr_name"]),
("parent.attr_name", ["parent", "attr_name"]),
("nested.parent.attr_name", ["nested", "parent", "attr_name"]),
("nested.parent.attr_name", ["nested", "parent", "attr_name"]),
("attr_name[0]", ["attr_name", "[0]"]),
("parent.attr_name[0]", ["parent", "attr_name", "[0]"]),
("attr_name[0][1]", ["attr_name", "[0]", "[1]"]),
('attr_name[0]["some_key"]', ["attr_name", "[0]", '["some_key"]']),
(
'dict_attr["some_key"].attr_name["other_key"]',
["dict_attr", '["some_key"]', "attr_name", '["other_key"]'],
),
],
)
def test_parse_full_access_path(full_access_path: str, expected: list[str]) -> None:
assert parse_full_access_path(full_access_path) == expected
@pytest.mark.parametrize(
"path_parts, expected",
[
(["attr_name"], "attr_name"),
(["parent", "attr_name"], "parent.attr_name"),
(["nested", "parent", "attr_name"], "nested.parent.attr_name"),
(["nested", "parent", "attr_name"], "nested.parent.attr_name"),
(["attr_name", "[0]"], "attr_name[0]"),
(["parent", "attr_name", "[0]"], "parent.attr_name[0]"),
(["attr_name", "[0]", "[1]"], "attr_name[0][1]"),
(["attr_name", "[0]", '["some_key"]'], 'attr_name[0]["some_key"]'),
(
["dict_attr", '["some_key"]', "attr_name", '["other_key"]'],
'dict_attr["some_key"].attr_name["other_key"]',
),
],
)
def test_get_path_from_path_parts(path_parts: list[str], expected: str) -> None:
assert get_path_from_path_parts(path_parts) == expected
@pytest.mark.parametrize( @pytest.mark.parametrize(
"attr_name, expected", "attr_name, expected",
[ [