modelguard-observatory / preflight.py
Hugdrigo's picture
Upload 28 files
85920d3 verified
Raw History Blame Contribute Delete
2.32 kB
"""Validate root-level Hugging Face Static Space files, manifest, and optional packaging.
Run: python preflight.py [path-to-zip]
"""
from pathlib import Path
import json, re, sys, hashlib, zipfile, yaml
ROOT=Path(__file__).resolve().parent
EXPECTED={'index.html','styles.css','app.js','engine.js','README.md','LICENSE','evaluation_snapshots.json','benchmark_manifest.json','source_modelops_engine.js','train.json','iid_test.json','challenge.json'}
readme=(ROOT/'README.md').read_text(encoding='utf-8')
assert readme.startswith('---\n')
metadata=yaml.safe_load(readme.split('---',2)[1])
assert metadata['sdk']=='static'
assert metadata['app_file']=='index.html'
assert metadata['license']=='mit'
assert len(metadata['short_description']) <= 60
assert metadata['colorFrom'] in ('red','yellow','green','blue','indigo','purple','pink','gray')
assert metadata['colorTo'] in ('red','yellow','green','blue','indigo','purple','pink','gray')
assert all((ROOT/n).is_file() for n in EXPECTED)
manifest=json.loads((ROOT/'benchmark_manifest.json').read_text())
data=(ROOT/'evaluation_snapshots.json').read_bytes()
assert manifest['evaluationSha256']==hashlib.sha256(data).hexdigest()
rows=json.loads(data)['rows']
assert len(rows)==manifest['predictionRows']==736
assert manifest['trainCount']==842 and manifest['iidCount']==130 and manifest['challengeCount']==54
for f,v in manifest['inputSha256'].items():assert hashlib.sha256((ROOT/f).read_bytes()).hexdigest()==v
assert 'src="engine.js"' in (ROOT/'index.html').read_text()
assert 'src="app.js"' in (ROOT/'index.html').read_text()
assert 'script src="http' not in (ROOT/'index.html').read_text()
assert not re.search(r'(api[_-]?key|secret|private[_-]?token)\s*[:=]\s*[\"\']\w+',readme,re.I)
print('PASS metadata, root sources, SHA-256 manifests, and sample counts')
if len(sys.argv)>1:
p=Path(sys.argv[1]);assert p.is_file()
with zipfile.ZipFile(p) as z:
assert z.testzip() is None
names=z.namelist()
assert len(names)==len(set(names))
assert all('/' not in name and not name.startswith('.') for name in names)
assert len(names)==len(list(ROOT.glob('*')))
assert EXPECTED.issubset(set(names))
for name in names:assert z.read(name)==(ROOT/name).read_bytes()
print(f'PASS ZIP integrity: {len(names)} root-level files and byte-for-byte match')
print('PREFLIGHT PASS')