gabriel / muse public
attributes.py python
82 lines 2.6 KB
6acddccb fix: restore structured --help output for all CLI commands Gabriel Cardona <gabriel@tellurstori.com> 1d ago
1 """muse attributes — display the ``.museattributes`` merge-strategy rules.
2
3 Reads and pretty-prints the ``.museattributes`` file from the current
4 repository, showing the ``[meta]`` domain (if set) and each rule's path
5 pattern, dimension, and strategy.
6
7 Usage::
8
9 muse attributes # tabular display
10 muse attributes --json # JSON object with meta + rules array
11 """
12
13 from __future__ import annotations
14
15 import argparse
16 import json
17
18 from muse.core.attributes import load_attributes, read_attributes_meta
19 from muse.core.repo import require_repo
20
21
22 def register(subparsers: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
23 """Register the attributes subcommand."""
24 parser = subparsers.add_parser(
25 "attributes",
26 help="Display the .museattributes merge-strategy rules.",
27 description=__doc__,
28 formatter_class=argparse.RawDescriptionHelpFormatter,
29 )
30 parser.add_argument("--json", action="store_true", dest="output_json",
31 help="Output rules as JSON.")
32 parser.set_defaults(func=run)
33
34
35 def run(args: argparse.Namespace) -> None:
36 """Display the ``.museattributes`` merge-strategy rules."""
37 output_json: bool = args.output_json
38
39 root = require_repo()
40 meta = read_attributes_meta(root)
41 rules = load_attributes(root)
42
43 if output_json:
44 payload: dict[str, str | list[dict[str, str | int]]] = {}
45 domain_val = meta.get("domain")
46 if domain_val is not None:
47 payload["domain"] = domain_val
48 payload["rules"] = [
49 {
50 "path_pattern": r.path_pattern,
51 "dimension": r.dimension,
52 "strategy": r.strategy,
53 "source_index": r.source_index,
54 }
55 for r in rules
56 ]
57 print(json.dumps(payload, indent=2))
58 return
59
60 if not rules:
61 print("No .museattributes file found (or file is empty).")
62 print(
63 "Create one at the repository root to declare per-path merge strategies."
64 )
65 return
66
67 # Header: domain from [meta] if present
68 domain_val = meta.get("domain")
69 if domain_val is not None:
70 print(f"Domain: {domain_val}")
71 print("")
72
73 # Compute column widths for aligned output.
74 pat_w = max(len(r.path_pattern) for r in rules)
75 dim_w = max(len(r.dimension) for r in rules)
76
77 print(f"{'Path pattern':<{pat_w}} {'Dimension':<{dim_w}} Strategy")
78 print(f"{'-' * pat_w} {'-' * dim_w} --------")
79 for rule in rules:
80 print(
81 f"{rule.path_pattern:<{pat_w}} {rule.dimension:<{dim_w}} {rule.strategy}"
82 )