-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Expand file tree
/
Copy path_installed_list_json.py
More file actions
84 lines (66 loc) 路 2.78 KB
/
Copy path_installed_list_json.py
File metadata and controls
84 lines (66 loc) 路 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"""Private JSON output helpers for installed preset and extension lists.
This module intentionally serves only the two installed-list commands. Their
human-facing renderers retain the legacy manager records, while this adapter
defines the public machine-readable wire contract.
"""
from __future__ import annotations
import json
from typing import Any, NoReturn
import typer
from typer.core import TyperCommand
try:
from typer._click.exceptions import UsageError as _UsageError
except ModuleNotFoundError as error:
if error.name != "typer._click":
raise
from click import UsageError as _UsageError
class InstalledListJSONCommand(TyperCommand):
"""Keep JSON list parse failures on the JSON error contract."""
def make_context(self, info_name, args, parent=None, **extra):
json_output = "--json" in args
try:
return super().make_context(info_name, args, parent=parent, **extra)
except _UsageError as error:
if json_output:
emit_json_error(error, exit_code=error.exit_code)
raise
def _normalized_source(source: Any) -> dict[str, str]:
"""Return the stable public source shape for an installed record."""
if not isinstance(source, dict):
return {"kind": "local"}
kind = source.get("kind")
if kind == "local":
return {"kind": "local"}
if kind == "catalog":
catalog = source.get("catalog")
if isinstance(catalog, str) and catalog.strip():
return {"kind": "catalog", "catalog": catalog}
return {"kind": "local"}
def installed_list_item(record: dict[str, Any], *, include_hooks: bool) -> dict[str, Any]:
"""Return the canonical public JSON object for one installed record."""
provides = record["_json_provides"]
if not include_hooks:
provides = {
"commands": provides["commands"],
"templates": provides["templates"],
"scripts": provides["scripts"],
}
return {
"id": record["id"],
"name": record["name"],
"description": record["description"],
"version": record["version"],
"author": record["_json_author"],
"priority": record["priority"],
"enabled": record["enabled"],
"source": _normalized_source(record["_json_source"]),
"provides": provides,
}
def emit_json(value: Any) -> None:
"""Write one JSON value to stdout without Rich rendering."""
typer.echo(json.dumps(value, ensure_ascii=False))
def emit_json_error(error: Exception, exit_code: int = 1) -> NoReturn:
"""Write the list-command error contract and terminate unsuccessfully."""
message = str(error).strip() or error.__class__.__name__
typer.echo(json.dumps({"error": message}, ensure_ascii=False), err=True)
raise typer.Exit(code=exit_code)