"""Expliziter, SHA-256-geprüfter Download des lokalen Erkennungsmodells.""" import argparse import hashlib import json import os from pathlib import Path import tempfile import urllib.request def main(): root = Path(__file__).resolve().parent.parent parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--state-dir", type=Path, default=Path(os.environ.get("HALLOWEEN_STATE_DIR", root / "data"))) args = parser.parse_args() manifest = json.loads((root / "halloween/nanodet-model.json").read_text()) target = args.state_dir / "models" / manifest["file"] if target.exists() and hashlib.sha256(target.read_bytes()).hexdigest() == manifest["sha256"]: print(f"Modell bereits geprüft: {target}") return target.parent.mkdir(parents=True, exist_ok=True) temp = None try: with tempfile.NamedTemporaryFile(dir=target.parent, delete=False) as output: temp = Path(output.name) digest, size = hashlib.sha256(), 0 with urllib.request.urlopen(manifest["url"], timeout=30) as response: while block := response.read(65536): size += len(block) if size > manifest["size"]: raise ValueError("Modell größer als erwartet") digest.update(block) output.write(block) if size != manifest["size"] or digest.hexdigest() != manifest["sha256"]: raise ValueError("Modell-Prüfsumme oder Größe stimmt nicht") output.flush() os.fsync(output.fileno()) os.replace(temp, target) print(f"Modell installiert und SHA-256 geprüft: {target}") finally: if temp is not None: temp.unlink(missing_ok=True) if __name__ == "__main__": main()