From 56393d4357332cb7893c95aef07f7f5e3e76a3ac Mon Sep 17 00:00:00 2001 From: Matthias Veit Date: Tue, 16 Jan 2024 15:09:55 +0100 Subject: [PATCH] [resotocore][fix] table: rendering of complex props (#1881) * [resotocore][fix] table: rendering of complex props * fix linter --- resotocore/resotocore/cli/__init__.py | 4 +--- resotocore/resotocore/cli/command.py | 21 +++++++++++++++------ resotocore/tests/resotocore/cli/cli_test.py | 3 ++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/resotocore/resotocore/cli/__init__.py b/resotocore/resotocore/cli/__init__.py index d334a63f4e..71ec2bd860 100644 --- a/resotocore/resotocore/cli/__init__.py +++ b/resotocore/resotocore/cli/__init__.py @@ -190,9 +190,7 @@ def at_idx(current: JsonElement, idx: int) -> Optional[Any]: else: child = current[prop] if isinstance(child, list): - if index is None: - return child - elif index is True: + if index is None or index is True: return [at_idx(e, idx + 1) for e in child] elif index < len(child): return at_idx(child[index], idx + 1) diff --git a/resotocore/resotocore/cli/command.py b/resotocore/resotocore/cli/command.py index 68a4a440f4..6d5d105e0c 100644 --- a/resotocore/resotocore/cli/command.py +++ b/resotocore/resotocore/cli/command.py @@ -116,8 +116,8 @@ ArrayKind, PropertyPath, TransformKind, - AnyKind, EmptyPath, + any_kind, ) from resotocore.model.resolve_in_graph import NodePath from resotocore.model.typed_model import to_json, to_js, from_js @@ -2716,23 +2716,32 @@ def to_csv_string(lst: List[Any]) -> str: yield to_csv_string(result) async def json_table_stream(in_stream: JsStream, model: Model) -> JsGen: - def kind_of(path: List[str]) -> str: + def kind_of(path: List[str]) -> Kind: if path[0] in Section.lookup_sections: return kind_of(path[2:]) if path[0] in Section.content: path = path[1:] kind = model.kind_by_path(path) if isinstance(kind, TransformKind): - return kind.source_kind.fqn if kind.source_kind else AnyKind().fqn + return kind.source_kind if kind.source_kind else any_kind else: - return kind.fqn + return kind + + def render_prop(elem: JsonElement) -> JsonElement: + # For table output, we want to show a single element: create a string from complex or list element. + if isinstance(elem, dict): + return ", ".join(f"{k}={render_prop(v)}" for k, v in sorted(elem.items())) + elif isinstance(elem, list): + return ", ".join(str(render_prop(e)) for e in elem) + else: + return elem # header columns yield { "columns": [ { "name": name, - "kind": kind_of(path), + "kind": kind_of(path).fqn, "display": " ".join(word.capitalize() for word in name.split("_")), } for path, name in props_to_show @@ -2744,7 +2753,7 @@ def kind_of(path: List[str]) -> str: if node := get_node(elem): yield { "id": node["id"], - "row": {name: js_value_at(node, prop_path) for prop_path, name in props_to_show}, + "row": {name: render_prop(js_value_at(node, path)) for path, name in props_to_show}, } def markdown_stream(in_stream: JsStream) -> JsGen: diff --git a/resotocore/tests/resotocore/cli/cli_test.py b/resotocore/tests/resotocore/cli/cli_test.py index 174973c953..bfc8c47066 100644 --- a/resotocore/tests/resotocore/cli/cli_test.py +++ b/resotocore/tests/resotocore/cli/cli_test.py @@ -1,7 +1,6 @@ from typing import List import pytest -from aiostream import stream from resotocore.cli import strip_quotes, js_value_at, args_parts_parser, args_parts_unquoted_parser, list_sink from resotocore.cli.cli import multi_command_parser, CLIService @@ -250,6 +249,8 @@ def test_js_value_at() -> None: assert js_value_at(js, "b[*].b[*]") == [[1, 2, 3], [1, 2, 3]] assert js_value_at(js, "b[*].b[2]") == [3, 3] assert js_value_at(js, "b[1].b[2]") == 3 + js = {"checks": [{"id": "1", "name": "foo"}, {"id": "2", "name": "bar"}]} + assert js_value_at(js, "checks.id") == ["1", "2"] def test_escape_character_parsing() -> None: