Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: test conformance lint typecheck check all
.PHONY: test conformance lint typecheck check all sync-schema

# Unit tests — the implementation's own suite. Hermetic and offline.
test:
Expand All @@ -11,6 +11,11 @@ test:
conformance:
pytest conformance -q

# Refresh the bundled JSON Schema from fruwehq/harel at the matching version tag
# (or HAREL_SPEC_DIR=/path/to/harel). The schema-drift test guards that they match.
sync-schema:
python scripts/sync_schema.py

lint:
ruff check .

Expand Down
61 changes: 61 additions & 0 deletions scripts/sync_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Refresh the bundled JSON Schema from the spec repo (fruwehq/harel).

Writes ``src/harel/data/machine.schema.json`` from harel's
``schema/machine.schema.json`` at the tag matching this package's version (falling back
to ``main``), or from a local checkout via ``HAREL_SPEC_DIR``. This removes the manual
copy step; the schema-drift test still guards that the two stay in sync.

Usage: ``python scripts/sync_schema.py`` (or ``make sync-schema``).
"""

from __future__ import annotations

import json
import os
import re
import sys
import urllib.error
import urllib.request
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
DEST = ROOT / "src" / "harel" / "data" / "machine.schema.json"
ABOUT = ROOT / "src" / "harel" / "__about__.py"


def _version() -> str:
m = re.search(r'__version__\s*=\s*"([^"]+)"', ABOUT.read_text(encoding="utf-8"))
if m is None:
raise SystemExit(f"could not read version from {ABOUT}")
return m.group(1)


def _fetch() -> str:
override = os.environ.get("HAREL_SPEC_DIR")
if override:
return (Path(override) / "schema" / "machine.schema.json").read_text(encoding="utf-8")
last: Exception | None = None
for ref in (f"v{_version()}", "main"):
url = f"https://raw.githubusercontent.com/fruwehq/harel/{ref}/schema/machine.schema.json"
try:
with urllib.request.urlopen(url, timeout=10) as resp: # noqa: S310 (fixed host)
return resp.read().decode("utf-8")
except urllib.error.URLError as exc:
last = exc
raise SystemExit(f"could not fetch schema from fruwehq/harel: {last}")


def main() -> int:
text = _fetch()
json.loads(text) # sanity check: valid JSON before overwriting
if DEST.read_text(encoding="utf-8") == text:
print(f"{DEST.relative_to(ROOT)} already up to date")
return 0
DEST.write_text(text, encoding="utf-8")
print(f"updated {DEST.relative_to(ROOT)}")
return 0


if __name__ == "__main__":
sys.exit(main())
Loading