From dcbb5d6da2c3c33d9a8d767fcfca422d23311687 Mon Sep 17 00:00:00 2001 From: Matthias Veit Date: Wed, 6 Dec 2023 10:12:24 +0100 Subject: [PATCH] [resotocore][fix] Use the property path if existing (#1849) --- resotocore/resotocore/cli/command.py | 8 ++++---- resotocore/resotocore/model/model.py | 16 +++++++++++----- resotocore/tests/resotocore/cli/command_test.py | 6 ++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/resotocore/resotocore/cli/command.py b/resotocore/resotocore/cli/command.py index 13f1bcd91c..2e6285cfec 100644 --- a/resotocore/resotocore/cli/command.py +++ b/resotocore/resotocore/cli/command.py @@ -1923,7 +1923,7 @@ def kind_name(p: Property) -> str: return {"name": kind.fqn} def property_defined_in(model: Model, path_: str) -> List[str]: - path = PropertyPath.from_path(path_) + path = PropertyPath.from_string(path_) return [ kind.fqn for kind in model.complex_kinds() @@ -2600,7 +2600,7 @@ def default_props_to_show() -> List[Tuple[List[str], str]]: for name in chain(predicate_names, sort_names): if name not in self.all_default_props and name not in local_paths: local_paths.add(name) - path = PropertyPath.from_path(name).unescaped_parts() + path = PropertyPath.from_string(name).unescaped_parts() result.append((path, path[-1])) if ctx.query_options.get("history") is not True: result.extend(self.default_live_properties_to_show) @@ -2609,7 +2609,7 @@ def default_props_to_show() -> List[Tuple[List[str], str]]: return result def adjust_path(prop_path: str) -> List[str]: - return PropertyPath.from_path(ctx.variable_in_section(prop_path)).unescaped_parts() + return PropertyPath.from_string(ctx.variable_in_section(prop_path)).unescaped_parts() def to_str(name: str, elem: JsonElement) -> str: if isinstance(elem, dict): @@ -2713,7 +2713,7 @@ def kind_of(path: List[str]) -> str: return kind_of(path[2:]) if path[0] in Section.content: path = path[1:] - kind = model.kind_by_path(".".join(path)) + kind = model.kind_by_path(path) if isinstance(kind, TransformKind): return kind.source_kind.fqn if kind.source_kind else AnyKind().fqn else: diff --git a/resotocore/resotocore/model/model.py b/resotocore/resotocore/model/model.py index 2b892cac4f..1c76780a10 100644 --- a/resotocore/resotocore/model/model.py +++ b/resotocore/resotocore/model/model.py @@ -161,7 +161,13 @@ def any_prop() -> Property: class PropertyPath: @staticmethod - def from_path(path: str) -> PropertyPath: + def from_list(path: List[str]) -> PropertyPath: + # remove index accesses from the path (e.g. [23] -> "[]", [*] -> "[]") + no_index = ".".join(array_index_re.sub("[]", a) for a in path) + return PropertyPath(path, no_index) + + @staticmethod + def from_string(path: str) -> PropertyPath: # remove index accesses from the path (e.g. [23] -> "[]", [*] -> "[]") no_index = array_index_re.sub("[]", path) return PropertyPath(prop_path_parser.parse(no_index), no_index) @@ -1366,14 +1372,14 @@ def aggregate_roots(self) -> Iterator[ComplexKind]: if k.aggregate_root: yield k - def property_by_path(self, path_: str) -> ResolvedProperty: - path = PropertyPath.from_path(path_) + def property_by_path(self, path_: Union[str, List[str]]) -> ResolvedProperty: + path = PropertyPath.from_string(path_) if isinstance(path_, str) else PropertyPath.from_list(path_) found: Optional[ResolvedProperty] = first(lambda prop: prop.path.same_as(path), self.__property_kind_by_path) # if the path is not known according to known model: it could be anything. return found if found else ResolvedProperty(path, Property.any_prop(), AnyKind()) - def kind_by_path(self, path_: str) -> Kind: - return self.property_by_path(path_).kind + def kind_by_path(self, path: Union[str, List[str]]) -> Kind: + return self.property_by_path(path).kind def coerce(self, js: Json) -> Json: try: diff --git a/resotocore/tests/resotocore/cli/command_test.py b/resotocore/tests/resotocore/cli/command_test.py index 71978bc39e..db6683da38 100644 --- a/resotocore/tests/resotocore/cli/command_test.py +++ b/resotocore/tests/resotocore/cli/command_test.py @@ -600,16 +600,18 @@ async def test_list_command(cli: CLI) -> None: # List supports markdown output result = await cli.execute_cli_command( - 'json {"id": "foo", "reported":{}, "name": "a", "some_int": 1} | list --json-table name, some_int', stream.list + 'json {"id": "foo", "reported":{}, "name": "a", "some_int": 1, "tags": {"foo․bla․bar.test.rest.best.":"yup"}} | list --json-table name, some_int, tags.`foo․bla․bar.test.rest.best.`', + stream.list, ) assert result[0] == [ { "columns": [ {"display": "Name", "kind": "string", "name": "name"}, {"display": "Some Int", "kind": "int32", "name": "some_int"}, + {"display": "Foo․bla․bar.test.rest.best.", "kind": "string", "name": "foo․bla․bar.test.rest.best."}, ], }, - {"id": "foo", "row": {"name": "a", "some_int": 1}}, + {"id": "foo", "row": {"foo․bla․bar.test.rest.best.": "yup", "name": "a", "some_int": 1}}, ] # List supports only markdown or csv, but not both at the same time