"""Small local packaging and translation checks; not a replacement for hassfest.""" import json from pathlib import Path import struct import subprocess root = Path(__file__).resolve().parents[1] component = root / "custom_components" / "heating_mpc" manifest = json.loads((component / "manifest.json").read_text()) assert manifest["domain"] == "heating_mpc" assert manifest["config_flow"] is True assert manifest["iot_class"] == "local_polling" assert not manifest["requirements"], "Model inference should remain dependency-free" json.loads((root / "hacs.json").read_text()) # A version bump needs release notes (AGENTS.md: no version without documentation). assert f"## {manifest['version']} " in (root / "CHANGELOG.md").read_text(), \ f"CHANGELOG.md has no entry for {manifest['version']}" def keys(value, prefix=()): if not isinstance(value, dict): return {prefix} return set().union(*(keys(child, (*prefix, key)) for key, child in value.items())) strings = json.loads((component / "strings.json").read_text()) for language in ("en", "ro"): translated = json.loads((component / "translations" / f"{language}.json").read_text()) assert keys(strings) == keys(translated), f"Translation keys differ: {language}" # Brand icons (HA 2026.3+): square transparent PNGs; see scripts/make_brand_icons.py. for name, size in (("icon.png", 256), ("icon@2x.png", 512), ("dark_icon.png", 256), ("dark_icon@2x.png", 512)): png = (component / "brand" / name).read_bytes() assert png[:8] == b"\x89PNG\r\n\x1a\n" and png[12:16] == b"IHDR", f"{name} is not a PNG" width, height, _depth, color_type = struct.unpack(">IIBB", png[16:26]) assert (width, height) == (size, size), f"{name} is {width}x{height}, expected {size}x{size}" assert color_type == 6, f"{name} needs an alpha channel" tracked = subprocess.check_output(["git", "ls-files", "custom_components"], cwd=root, text=True).splitlines() assert not any("__pycache__" in path or path.endswith((".pyc", ".pyo", ".DS_Store")) for path in tracked) print("Package metadata, translations, brand icons and tracked component files passed")