b9ab1263c2
Closes #157. Distributes the 1,026-line manifest.py across four focused modules: - _manifest_util.py: ManifestError + _as_json_object (shared base) - manifest_git.py: GitEntry, GitUser, git-gate config helpers - manifest_egress.py: EgressRoute, EgressConfig, PipelockRoutePolicy - manifest_agent.py: AgentProvider, Agent manifest.py is now the residual orchestration layer: Bottle, Manifest, and re-exports of all public names so existing callers are unaffected. All 867 unit tests pass.
25 lines
864 B
Python
25 lines
864 B
Python
"""Shared manifest primitives used by all manifest sub-modules."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import cast
|
|
|
|
|
|
class ManifestError(Exception):
|
|
"""A manifest file (or the manifest tree) is invalid."""
|
|
|
|
|
|
def _as_json_object(value: object, label: str) -> dict[str, object]:
|
|
"""Assert that `value` is a JSON object (str-keyed dict) and return
|
|
a view typed as `dict[str, object]` so downstream `.get(...)` calls
|
|
have a typed surface."""
|
|
if not isinstance(value, dict):
|
|
raise ManifestError(f"{label} must be a JSON object (was {type(value).__name__})")
|
|
items = cast(dict[object, object], value)
|
|
out: dict[str, object] = {}
|
|
for k, v in items.items():
|
|
if not isinstance(k, str):
|
|
raise ManifestError(f"{label} keys must be strings (found {type(k).__name__})")
|
|
out[k] = v
|
|
return out
|