3"""Load the single machine-readable GitHub tracker authority."""
5from __future__
import annotations
9from dataclasses
import dataclass
10from functools
import lru_cache
11from pathlib
import Path
12from typing
import NoReturn
14from work_git
import WorkError
16REPOSITORY_RE = re.compile(
r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$")
17LOGIN_RE = re.compile(
r"^[A-Za-z0-9-]{1,39}$")
21def fail(message: str, cause: BaseException |
None =
None) -> NoReturn:
22 """Raise one consistently constructed tracker-schema error."""
23 error = WorkError(message)
25 raise error
from cause
29@dataclass(frozen=True)
31 """Exact GitHub target plus allowed project field names."""
37 statuses: tuple[str, ...]
38 tracks: tuple[str, ...]
41def _string_list(payload: object, key: str) -> tuple[str, ...]:
42 """Read one non-empty duplicate-free string list."""
43 if not isinstance(payload, dict):
44 fail(
"tracker schema root must be an object")
45 raw = payload.get(key)
46 if not isinstance(raw, list)
or not raw:
47 fail(f
"tracker schema {key} must be a non-empty list")
49 if any(
not isinstance(value, str)
or not value
or not value.isprintable()
for value
in values):
50 fail(f
"tracker schema {key} contains an invalid value")
51 if len(set(values)) != len(values):
52 fail(f
"tracker schema {key} contains a duplicate")
57def tracker_schema() -> TrackerSchema:
58 """Load and validate ``scripts/dev/work/tracker.json`` once per process."""
59 path = Path(__file__).resolve().parents[1] /
"tracker.json"
61 payload = json.loads(path.read_text(encoding=
"ascii"))
62 except (OSError, UnicodeError, json.JSONDecodeError)
as exc:
63 fail(f
"tracker schema could not be read: {exc}", exc)
73 valid_root = isinstance(payload, dict)
and set(payload) == expected
74 if not valid_root
or payload.get(
"schema_version") != SCHEMA_VERSION:
75 fail(
"tracker schema keys or version are unsupported")
76 host = payload[
"github_host"]
77 repository = payload[
"repository"]
78 owner = payload[
"project_owner"]
79 number = payload[
"project_number"]
80 if host !=
"github.com":
81 fail(
"tracker schema must pin github.com")
82 if not isinstance(repository, str)
or REPOSITORY_RE.fullmatch(repository)
is None:
83 fail(
"tracker schema repository must be owner/name")
84 if not isinstance(owner, str)
or LOGIN_RE.fullmatch(owner)
is None:
85 fail(
"tracker schema project_owner is invalid")
86 if not isinstance(number, int)
or isinstance(number, bool)
or number < 1:
87 fail(
"tracker schema project_number must be positive")
90 repository=repository,
92 project_number=number,
93 statuses=_string_list(payload,
"statuses"),
94 tracks=_string_list(payload,
"tracks"),