thundercode commited on
Commit
db58bce
·
verified ·
1 Parent(s): 7237a5c

release: add tools/hf_verify.py

Browse files
Files changed (1) hide show
  1. tools/hf_verify.py +114 -0
tools/hf_verify.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Verify the Hugging Face release: re-download every uploaded file and compare sha256 + size.
2
+
3
+ This is an INDEPENDENT check — it does not trust the upload step. It reads the manifest, downloads
4
+ each artifact from the Hub over direct HTTPS (proxies disabled, which matters in the authoring
5
+ sandbox), hashes the bytes it received, and compares against the locally-computed hash.
6
+
7
+ Note: `hf_hub_download` is deliberately NOT used here — in this environment it returned an empty
8
+ file (sha256 e3b0c442...), which would have produced a false FAIL. Direct HTTPS is the honest check.
9
+ """
10
+ import hashlib
11
+ import json
12
+ import os
13
+ import sys
14
+ import urllib.request
15
+
16
+ REPO_ID = "thundercode/SatQuery"
17
+ HERE = os.path.dirname(os.path.abspath(__file__))
18
+ REPO = os.path.abspath(os.path.join(HERE, "..", "repo"))
19
+ SRC = r"C:/Users/anish/satquery-ai"
20
+
21
+
22
+ def sha256_of(path, chunk=1 << 20):
23
+ h = hashlib.sha256()
24
+ with open(path, "rb") as fh:
25
+ while True:
26
+ b = fh.read(chunk)
27
+ if not b:
28
+ break
29
+ h.update(b)
30
+ return h.hexdigest()
31
+
32
+
33
+ def sha256_of_bytes(b):
34
+ return hashlib.sha256(b).hexdigest()
35
+
36
+
37
+ def opener_no_proxy():
38
+ return urllib.request.build_opener(urllib.request.ProxyHandler({}))
39
+
40
+
41
+ def fetch(url, token, opener):
42
+ req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
43
+ with opener.open(req, timeout=120) as r:
44
+ return r.read()
45
+
46
+
47
+ def main():
48
+ token = os.environ.get("HF_TOKEN")
49
+ if not token:
50
+ print("ERROR: HF_TOKEN not set.")
51
+ return 2
52
+
53
+ opener = opener_no_proxy()
54
+
55
+ # repo metadata (sizes + listing) over the API
56
+ api = json.loads(
57
+ fetch(f"https://huggingface.co/api/models/{REPO_ID}?blobs=true", token, opener).decode()
58
+ )
59
+ print(f"repo : {api.get('id')}")
60
+ print(f"private : {api.get('private')}")
61
+ print(f"sha (HEAD) : {api.get('sha')}")
62
+ print(f"lastModified : {api.get('lastModified')}")
63
+ remote = {s["rfilename"]: s for s in (api.get("siblings") or [])}
64
+ print(f"files on Hub : {len(remote)}")
65
+ print()
66
+
67
+ manifest = json.load(open(os.path.join(REPO, "models", "manifest.json"), encoding="utf-8"))
68
+
69
+ ok = bad = 0
70
+ print(f"{'STATUS':7} {'hf_path':40} {'remote bytes':>14} {'local bytes':>13}")
71
+ print("-" * 82)
72
+ for a in manifest["artifacts"]:
73
+ hf_path = a["hf_path"]
74
+ local = os.path.join(SRC, a["path"])
75
+ local_bytes = os.path.getsize(local)
76
+ local_hash = sha256_of(local)
77
+
78
+ s = remote.get(hf_path)
79
+ if s is None:
80
+ print(f"{'MISSING':7} {hf_path:40} {'-':>14} {local_bytes:>13,}")
81
+ bad += 1
82
+ continue
83
+ remote_bytes = s.get("size")
84
+ try:
85
+ content = fetch(
86
+ f"https://huggingface.co/{REPO_ID}/resolve/main/{hf_path}", token, opener
87
+ )
88
+ except Exception as e:
89
+ print(f"{'ERROR':7} {hf_path:40} {'-':>14} {local_bytes:>13,} {e}")
90
+ bad += 1
91
+ continue
92
+ remote_hash = sha256_of_bytes(content)
93
+
94
+ size_ok = remote_bytes == local_bytes == len(content)
95
+ hash_ok = remote_hash == local_hash
96
+ status = "MATCH" if (size_ok and hash_ok) else "DIFFER"
97
+ ok += status == "MATCH"
98
+ bad += status != "MATCH"
99
+ print(f"{status:7} {hf_path:40} {remote_bytes:>14,} {local_bytes:>13,}")
100
+ if not hash_ok:
101
+ print(f" local sha256 {local_hash}")
102
+ print(f" remote sha256 {remote_hash}")
103
+
104
+ print()
105
+ print(f"artifacts verified : {ok}")
106
+ print(f"artifacts failed : {bad}")
107
+ print()
108
+ for name in ["README.md", "MODEL_CARD.md", "models/manifest.json", "models/checksums.sha256"]:
109
+ print(f" {'OK ' if name in remote else 'MISS'} {name}")
110
+ return 0 if bad == 0 else 1
111
+
112
+
113
+ if __name__ == "__main__":
114
+ sys.exit(main())