gabriel / muse public
attributes.py python
72 lines 2.2 KB
e6786943 feat: upgrade to Python 3.14, drop from __future__ import annotations Gabriel Cardona <cgcardona@gmail.com> 5d 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 import json
14
15 import typer
16
17 from muse.core.attributes import load_attributes, read_attributes_meta
18 from muse.core.repo import require_repo
19
20 app = typer.Typer()
21
22
23 @app.callback(invoke_without_command=True)
24 def attributes(
25 ctx: typer.Context,
26 output_json: bool = typer.Option(False, "--json", help="Output rules as JSON."),
27 ) -> None:
28 """Display the ``.museattributes`` merge-strategy rules."""
29 root = require_repo()
30 meta = read_attributes_meta(root)
31 rules = load_attributes(root)
32
33 if output_json:
34 payload: dict[str, str | list[dict[str, str | int]]] = {}
35 domain_val = meta.get("domain")
36 if domain_val is not None:
37 payload["domain"] = domain_val
38 payload["rules"] = [
39 {
40 "path_pattern": r.path_pattern,
41 "dimension": r.dimension,
42 "strategy": r.strategy,
43 "source_index": r.source_index,
44 }
45 for r in rules
46 ]
47 typer.echo(json.dumps(payload, indent=2))
48 return
49
50 if not rules:
51 typer.echo("No .museattributes file found (or file is empty).")
52 typer.echo(
53 "Create one at the repository root to declare per-path merge strategies."
54 )
55 return
56
57 # Header: domain from [meta] if present
58 domain_val = meta.get("domain")
59 if domain_val is not None:
60 typer.echo(f"Domain: {domain_val}")
61 typer.echo("")
62
63 # Compute column widths for aligned output.
64 pat_w = max(len(r.path_pattern) for r in rules)
65 dim_w = max(len(r.dimension) for r in rules)
66
67 typer.echo(f"{'Path pattern':<{pat_w}} {'Dimension':<{dim_w}} Strategy")
68 typer.echo(f"{'-' * pat_w} {'-' * dim_w} --------")
69 for rule in rules:
70 typer.echo(
71 f"{rule.path_pattern:<{pat_w}} {rule.dimension:<{dim_w}} {rule.strategy}"
72 )