mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-10 18:59:56 +00:00
ci: legible failures for malformed exceptions file; docs catch up
_parse_exceptions() now validates the document shape — top level must be a mapping, 'exceptions' must be a list, each entry a mapping, and YAML parse errors are caught — each failing with a ::error:: instead of an AttributeError traceback. CI output must say what to fix. Parametrised tests cover all four malformed shapes. docs/feedpak-spec-gate.md: the Limitations section still described the pre-flow-aware scanner (KEY_OPS, name-list-only receivers). Now states the actual residual gaps: function-parameter manifests are recognised by name only, and helper-mediated literal keys (song.py's _gap_fill_manifest_absent(manifest, "album")) are unseen by both the scan and the readers-complete guard, since they share one detector. Signed-off-by: topkoa <topkoa@gmail.com>
This commit is contained in:
@@ -182,9 +182,25 @@ def _parse_exceptions(text: str, origin: str) -> dict[str, str]:
|
||||
"""Parse an exceptions document into {key: tracking issue}."""
|
||||
import yaml # runtime dep (PyYAML is already in requirements.txt)
|
||||
|
||||
data = yaml.safe_load(text) or {}
|
||||
try:
|
||||
data = yaml.safe_load(text) or {}
|
||||
except yaml.YAMLError as e:
|
||||
_fail(f"{origin}: not valid YAML — {e}")
|
||||
sys.exit(1)
|
||||
# A malformed shape (list/string at top level, non-mapping entry) must fail
|
||||
# with a CI-legible error, not an AttributeError traceback.
|
||||
if not isinstance(data, dict):
|
||||
_fail(f"{origin}: top level must be a mapping with an 'exceptions' list, got {type(data).__name__}")
|
||||
sys.exit(1)
|
||||
entries = data.get("exceptions") or []
|
||||
if not isinstance(entries, list):
|
||||
_fail(f"{origin}: 'exceptions' must be a list, got {type(entries).__name__}")
|
||||
sys.exit(1)
|
||||
out: dict[str, str] = {}
|
||||
for entry in data.get("exceptions") or []:
|
||||
for entry in entries:
|
||||
if not isinstance(entry, dict):
|
||||
_fail(f"{origin}: each exception must be a mapping with 'key' and 'issue', got {type(entry).__name__}")
|
||||
sys.exit(1)
|
||||
key, issue = entry.get("key"), entry.get("issue")
|
||||
if not key or not issue:
|
||||
_fail(f"{origin}: every exception needs both 'key' and 'issue'")
|
||||
|
||||
Reference in New Issue
Block a user