mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-20 08:20:02 +02:00
creates functions to split full access paths and combine the atomic parts back together
This commit is contained in:
parent
036e80b920
commit
c75b203c3d
@ -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,
|
||||||
|
@ -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",
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user