Repository navigation
Expand file tree
/
Copy pathtransform.py
More file actions
92 lines (74 loc) · 2.48 KB
/
Copy pathtransform.py
File metadata and controls
92 lines (74 loc) · 2.48 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
85
86
87
88
89
90
91
92
#!/usr/bin/env python3
"""Normalize task records: read JSON from stdin, write normalized JSON to stdout.
Usage:
python transform.py < input.json > output.json
Exits non-zero on invalid input. No network access, fully deterministic.
"""
from __future__ import annotations
import json
import sys
from typing import Any
STATUS_MAP: dict[str, str] = {
"todo": "todo",
"to do": "todo",
"pending": "todo",
"doing": "doing",
"in progress": "doing",
"wip": "doing",
"done": "done",
"complete": "done",
"completed": "done",
}
_KEY_PRIORITY = {"id": 0, "title": 1, "status": 2}
def _normalize_status(value: Any) -> Any:
if not isinstance(value, str):
return value
key = value.strip().lower()
return STATUS_MAP.get(key, key)
def _ordered_keys(record: dict[str, Any]) -> list[str]:
return sorted(record.keys(), key=lambda k: (_KEY_PRIORITY.get(k, 3), k))
def _is_int(value: Any) -> bool:
try:
int(str(value).strip())
return True
except (TypeError, ValueError):
return False
def normalize(records: Any) -> list[dict[str, Any]]:
if not isinstance(records, list):
raise ValueError("input must be a JSON array")
normalized: list[dict[str, Any]] = []
for record in records:
if not isinstance(record, dict):
raise ValueError("each record must be a JSON object")
out: dict[str, Any] = {}
for key in _ordered_keys(record):
value = record[key]
if key == "status":
out[key] = _normalize_status(value)
elif key == "id":
out[key] = str(value).strip()
elif isinstance(value, str):
out[key] = value.strip()
else:
out[key] = value
normalized.append(out)
if normalized and all(_is_int(r.get("id", "")) for r in normalized):
normalized.sort(key=lambda r: int(str(r.get("id")).strip()))
else:
normalized.sort(key=lambda r: str(r.get("id", "")))
return normalized
def main() -> int:
try:
payload = json.load(sys.stdin)
except json.JSONDecodeError as exc:
print(f"error: invalid JSON on stdin: {exc}", file=sys.stderr)
return 1
try:
result = normalize(payload)
except ValueError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
json.dump(result, sys.stdout, ensure_ascii=False, separators=(",", ":"))
return 0
if __name__ == "__main__":
sys.exit(main())