Claude Code commited on
Commit
8445d86
·
1 Parent(s): e43439e

Claude Code: Create a verification script at HF Dataset Persistence Verification

Browse files

========================================

✅ Persistence fully configured - dataset: tao-shen/HuggingClaw-Home-data (auto-derived)
• HF_TOKEN: ✓ Set
• Dataset repo: tao-shen/HuggingClaw-Home-data
• AUTO_CREATE_DATASET: true
• Repository status: ✓ Exists

Result: Persistence is READY that tests t

Files changed (1) hide show
  1. scripts/verify_dataset.py +268 -0
scripts/verify_dataset.py ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ HF Dataset Persistence Verification Script
4
+ ============================================
5
+
6
+ Verifies the HuggingFace Dataset persistence layer configuration.
7
+ Can be imported as a module or run standalone for testing.
8
+
9
+ Usage:
10
+ python scripts/verify_dataset.py
11
+
12
+ # Or import from app.py:
13
+ from scripts.verify_dataset import verify_dataset, DatasetStatus
14
+ status = verify_dataset()
15
+ if status.ready:
16
+ print("Persistence is ready!")
17
+ """
18
+
19
+ import os
20
+ import sys
21
+ from pathlib import Path
22
+ from typing import NamedTuple, Optional
23
+ from dataclasses import dataclass
24
+
25
+ # Add parent directory to path for imports when run standalone
26
+ if __name__ == "__main__":
27
+ sys.path.insert(0, str(Path(__file__).parent.parent))
28
+
29
+ # Set timeout BEFORE importing huggingface_hub
30
+ os.environ.setdefault("HF_HUB_DOWNLOAD_TIMEOUT", "300")
31
+ os.environ.setdefault("HF_HUB_UPLOAD_TIMEOUT", "600")
32
+ # Suppress huggingface_hub progress bars and verbose logs
33
+ os.environ.setdefault("HF_HUB_DISABLE_PROGRESS_BARS", "1")
34
+ os.environ.setdefault("HF_HUB_VERBOSITY", "warning")
35
+
36
+ import logging
37
+ _logging = logging.getLogger("huggingface_hub")
38
+ _logging.setLevel(logging.WARNING)
39
+
40
+
41
+ @dataclass
42
+ class DatasetStatus:
43
+ """Status of HF Dataset persistence configuration."""
44
+ ready: bool
45
+ has_token: bool
46
+ has_repo: bool
47
+ auto_create: bool
48
+ repo_exists: bool
49
+ write_access: bool
50
+ repo_id: str
51
+ message: str
52
+ emoji: str
53
+
54
+
55
+ def get_dataset_repo_id() -> tuple[str, bool]:
56
+ """
57
+ Determine the dataset repository ID.
58
+
59
+ Returns:
60
+ (repo_id, was_auto_derived) tuple
61
+ """
62
+ # Try explicit env var first
63
+ repo_id = os.environ.get("OPENCLAW_DATASET_REPO", "")
64
+ if repo_id:
65
+ return repo_id, False
66
+
67
+ # Auto-derive from SPACE_ID (HF Spaces built-in)
68
+ space_id = os.environ.get("SPACE_ID", "")
69
+ if space_id:
70
+ # SPACE_ID = "username/SpaceName" → derive "username/SpaceName-data"
71
+ derived = f"{space_id}-data"
72
+ return derived, True
73
+
74
+ # Fallback: derive from HF_TOKEN username (local Docker)
75
+ hf_token = os.environ.get("HF_TOKEN")
76
+ if hf_token:
77
+ try:
78
+ from huggingface_hub import HfApi
79
+ api = HfApi(token=hf_token)
80
+ username = api.whoami()["name"]
81
+ return f"{username}/HuggingClaw-data", True
82
+ except Exception:
83
+ pass
84
+
85
+ return "", False
86
+
87
+
88
+ def verify_dataset() -> DatasetStatus:
89
+ """
90
+ Verify HF Dataset persistence configuration.
91
+
92
+ Returns:
93
+ DatasetStatus object with verification results
94
+ """
95
+ hf_token = os.environ.get("HF_TOKEN")
96
+ auto_create = os.environ.get("AUTO_CREATE_DATASET", "false").lower() in ("true", "1", "yes")
97
+
98
+ repo_id, was_auto_derived = get_dataset_repo_id()
99
+
100
+ # Check 1: HF_TOKEN
101
+ if not hf_token:
102
+ return DatasetStatus(
103
+ ready=False,
104
+ has_token=False,
105
+ has_repo=False,
106
+ auto_create=auto_create,
107
+ repo_exists=False,
108
+ write_access=False,
109
+ repo_id=repo_id,
110
+ message="HF_TOKEN not set - persistence disabled",
111
+ emoji="⚠️"
112
+ )
113
+
114
+ # Check 2: Repository ID
115
+ if not repo_id:
116
+ return DatasetStatus(
117
+ ready=False,
118
+ has_token=True,
119
+ has_repo=False,
120
+ auto_create=auto_create,
121
+ repo_exists=False,
122
+ write_access=False,
123
+ repo_id="",
124
+ message="Could not determine dataset repo (no SPACE_ID or OPENCLAW_DATASET_REPO)",
125
+ emoji="❌"
126
+ )
127
+
128
+ # Check 3: Verify connection and check if repo exists
129
+ from huggingface_hub import HfApi
130
+ api = HfApi(token=hf_token)
131
+
132
+ try:
133
+ # Test authentication
134
+ whoami = api.whoami()
135
+ username = whoami.get("name", "")
136
+
137
+ # Check if repo exists
138
+ try:
139
+ api.repo_info(repo_id=repo_id, repo_type="dataset")
140
+ repo_exists = True
141
+ except Exception:
142
+ repo_exists = False
143
+
144
+ # If repo doesn't exist and auto_create is false, warn
145
+ if not repo_exists and not auto_create:
146
+ return DatasetStatus(
147
+ ready=False,
148
+ has_token=True,
149
+ has_repo=True,
150
+ auto_create=False,
151
+ repo_exists=False,
152
+ write_access=True,
153
+ repo_id=repo_id,
154
+ message=f"AUTO_CREATE_DATASET=false - dataset '{repo_id}' must exist manually",
155
+ emoji="⚠️"
156
+ )
157
+
158
+ # If repo doesn't exist but auto_create is true, we can create it
159
+ if not repo_exists and auto_create:
160
+ return DatasetStatus(
161
+ ready=True,
162
+ has_token=True,
163
+ has_repo=True,
164
+ auto_create=True,
165
+ repo_exists=False,
166
+ write_access=True,
167
+ repo_id=repo_id,
168
+ message=f"Will auto-create dataset '{repo_id}' on first sync",
169
+ emoji="✅"
170
+ )
171
+
172
+ # All checks passed
173
+ source_info = " (auto-derived)" if was_auto_derived else ""
174
+ return DatasetStatus(
175
+ ready=True,
176
+ has_token=True,
177
+ has_repo=True,
178
+ auto_create=auto_create,
179
+ repo_exists=True,
180
+ write_access=True,
181
+ repo_id=repo_id,
182
+ message=f"Persistence fully configured - dataset: {repo_id}{source_info}",
183
+ emoji="✅"
184
+ )
185
+
186
+ except Exception as e:
187
+ # Connection failed
188
+ error_msg = str(e)
189
+ if "401" in error_msg or "authentication" in error_msg.lower():
190
+ return DatasetStatus(
191
+ ready=False,
192
+ has_token=True,
193
+ has_repo=True,
194
+ auto_create=auto_create,
195
+ repo_exists=False,
196
+ write_access=False,
197
+ repo_id=repo_id,
198
+ message=f"Authentication failed - check HF_TOKEN has write permissions",
199
+ emoji="❌"
200
+ )
201
+
202
+ return DatasetStatus(
203
+ ready=False,
204
+ has_token=True,
205
+ has_repo=True,
206
+ auto_create=auto_create,
207
+ repo_exists=False,
208
+ write_access=False,
209
+ repo_id=repo_id,
210
+ message=f"Connection failed: {error_msg[:100]}",
211
+ emoji="❌"
212
+ )
213
+
214
+
215
+ def print_status(status: DatasetStatus) -> None:
216
+ """Print formatted status to console."""
217
+ print(f"{status.emoji} {status.message}")
218
+
219
+ # Print additional details
220
+ details = []
221
+ if not status.has_token:
222
+ details.append(" • HF_TOKEN: NOT SET")
223
+ else:
224
+ details.append(f" • HF_TOKEN: {'✓ Set' if status.write_access else '✗ Invalid'}")
225
+
226
+ if not status.has_repo:
227
+ details.append(f" • OPENCLAW_DATASET_REPO: NOT SET (will auto-derive)")
228
+ else:
229
+ details.append(f" • Dataset repo: {status.repo_id}")
230
+
231
+ details.append(f" • AUTO_CREATE_DATASET: {os.environ.get('AUTO_CREATE_DATASET', 'false')}")
232
+
233
+ if status.repo_exists:
234
+ details.append(" • Repository status: ✓ Exists")
235
+ elif status.auto_create and status.has_token:
236
+ details.append(" • Repository status: Will be created on first sync")
237
+ else:
238
+ details.append(" • Repository status: ✗ Not found")
239
+
240
+ for detail in details:
241
+ print(detail)
242
+
243
+
244
+ def main() -> int:
245
+ """
246
+ Main entry point when run standalone.
247
+
248
+ Returns:
249
+ 0 if persistence is ready, 1 otherwise
250
+ """
251
+ print("HF Dataset Persistence Verification")
252
+ print("=" * 40)
253
+ print()
254
+
255
+ status = verify_dataset()
256
+ print_status(status)
257
+ print()
258
+
259
+ if status.ready:
260
+ print("Result: Persistence is READY")
261
+ return 0
262
+ else:
263
+ print("Result: Persistence is NOT ready")
264
+ return 1
265
+
266
+
267
+ if __name__ == "__main__":
268
+ sys.exit(main())