Coverage for flowr / cli / output.py: 100%
36 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-22 18:42 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-22 18:42 +0000
1"""Output formatting for CLI results."""
3import json
4from typing import Any
7def _format_dict_lines(data: dict[str, Any], indent: str = "") -> list[str]:
8 """Format a single dict as key-value lines."""
9 lines: list[str] = []
10 for key, value in data.items():
11 if isinstance(value, list):
12 if not value:
13 lines.append(f"{indent}{key}: (none)")
14 elif isinstance(value[0], dict):
15 lines.append(f"{indent}{key}:")
16 for item in value:
17 first = True
18 for k, v in item.items():
19 if first:
20 lines.append(f"{indent} - {k}: {v}")
21 first = False
22 else:
23 lines.append(f"{indent} {k}: {v}")
24 else:
25 for item in value:
26 lines.append(f"{indent}{key}: {item}")
27 elif isinstance(value, dict):
28 lines.append(f"{indent}{key}:")
29 lines.extend(_format_dict_lines(value, indent + " "))
30 else:
31 lines.append(f"{indent}{key}: {value}")
32 return lines
35def format_text(result: dict[str, Any] | list[dict[str, Any]]) -> str:
36 """Format a result dict or list of dicts as human-readable text."""
37 if isinstance(result, list):
38 lines: list[str] = []
39 for item in result:
40 lines.extend(_format_dict_lines(item))
41 lines.append("---")
42 if lines:
43 lines.pop()
44 return "\n".join(lines)
45 return "\n".join(_format_dict_lines(result))
48def format_json(result: Any) -> str: # noqa: ANN401
49 """Format a result as JSON."""
50 return json.dumps(result, indent=2)