Coverage for src/bayernwerk_client/formatting.py: 100%
40 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-17 13:07 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-17 13:07 +0000
1"""Generic, schema-less human-readable rendering for CLI output.
3Response shapes vary per endpoint/service and can change over time, so
4these render whatever comes back - a list of dicts as one indented
5paragraph per item, a single dict as indented key/value lines - rather
6than assuming fixed columns or fields. A wide table was tried first but
7discarded: flattening nested fields (customer, address, ...) into columns
8made it unreadable, and dropping them silently hid exactly the useful
9data. Shared across services (`map`, and later `efix`); service-specific
10renderers that pick out a curated "headline" for a well-known shape (like
11`map.formatting.render_orders` or `render_instance_tree`) live with that
12service instead.
13"""
15from __future__ import annotations
17from typing import Any
20def format_result(data: Any) -> str:
21 if isinstance(data, list):
22 if not data:
23 return "(leer)"
24 if all(isinstance(item, dict) for item in data):
25 return format_list(data)
26 return "\n".join(str(item) for item in data)
27 if isinstance(data, dict):
28 return format_dict(data)
29 return str(data)
32def format_list(items: list[dict[str, Any]]) -> str:
33 """One numbered paragraph per item, full contents indented via `format_dict`."""
34 blocks = []
35 for i, item in enumerate(items, start=1):
36 body = format_dict(item, indent=1)
37 blocks.append(f"[{i}]\n{body}" if body else f"[{i}]")
38 return "\n\n".join(blocks)
41def format_dict(obj: dict[str, Any], indent: int = 0) -> str:
42 pad = " " * indent
43 lines: list[str] = []
44 for key, value in obj.items():
45 if isinstance(value, dict):
46 if not value:
47 lines.append(f"{pad}{key}: {{}}")
48 else:
49 lines.append(f"{pad}{key}:")
50 lines.append(format_dict(value, indent + 1))
51 elif isinstance(value, list):
52 if not value:
53 lines.append(f"{pad}{key}: []")
54 elif all(isinstance(item, dict) for item in value):
55 lines.append(f"{pad}{key}:")
56 for i, item in enumerate(value):
57 lines.append(f"{pad} [{i}]")
58 lines.append(format_dict(item, indent + 2))
59 else:
60 lines.append(f"{pad}{key}: {', '.join(str(item) for item in value)}")
61 else:
62 lines.append(f"{pad}{key}: {_scalar(value)}")
63 return "\n".join(lines)
66def _scalar(value: Any) -> str:
67 return "" if value is None else str(value)