Spaces:
Paused
Paused
Download scripts/verify_space.py from mantrakp/component-studio: direct link, hf CLI and curl.
- Browser
- Download file 3.42 kB
-
https://huggingface.co/spaces/mantrakp/component-studio/resolve/main/scripts/verify_space.py
- Command line
-
hf download hf://spaces/mantrakp/component-studio/scripts/verify_space.py
-
curl -L -o verify_space.py https://huggingface.co/spaces/mantrakp/component-studio/resolve/main/scripts/verify_space.py
3.42 kB
| """Run real inference on an explicitly named deployed Space and verify its downloaded GLB/ZIP.""" | |
| import argparse | |
| import json | |
| import os | |
| from pathlib import Path | |
| import zipfile | |
| import time | |
| from gradio_client import Client, handle_file | |
| from huggingface_hub import get_token | |
| import trimesh | |
| def main(): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument('--space', required=True, help='Hugging Face owner/space') | |
| parser.add_argument('--image', type=Path) | |
| parser.add_argument('--prompt', default='') | |
| parser.add_argument('--animation-prompt', default='') | |
| parser.add_argument('--animation-seconds', type=float, default=6) | |
| parser.add_argument('--output-dir', type=Path, default=Path('outputs/hf-verification')) | |
| args = parser.parse_args() | |
| if not args.image and not args.prompt.strip(): | |
| parser.error('Supply --image, --prompt, or both') | |
| args.output_dir.mkdir(parents=True, exist_ok=True) | |
| client = Client(args.space, token=os.environ.get('HF_TOKEN') or get_token(), | |
| download_files=args.output_dir.resolve()) | |
| job = client.submit(handle_file(str(args.image)) if args.image else None, | |
| args.prompt, 8, 0, args.animation_prompt, args.animation_seconds, api_name='/generate') | |
| previous = None | |
| while not job.done(): | |
| update = job.status() | |
| current = (update.code.name, tuple(p.desc for p in update.progress_data or [])) | |
| if current != previous: | |
| print(json.dumps({'state': current[0], 'progress': current[1]}), flush=True) | |
| previous = current | |
| time.sleep(2) | |
| model, reference, views, bundle, status, manifest, video = job.result() | |
| (args.output_dir / f"{manifest['id']}.json").write_text(json.dumps(manifest, indent=2)) | |
| if args.animation_prompt: | |
| import struct | |
| raw = Path(model).read_bytes() | |
| size, kind = struct.unpack_from('<II', raw, 12) | |
| if kind != 0x4e4f534a: | |
| raise RuntimeError('Animated GLB has no JSON chunk') | |
| gltf = json.loads(raw[20:20 + size]) | |
| if not gltf.get('skins') or not gltf.get('animations'): | |
| raise RuntimeError('Requested animation returned a static mesh') | |
| if not video or not manifest.get('animation', {}).get('accepted'): | |
| raise RuntimeError('Animation lacks video or failed its technical/visual review') | |
| if manifest['status'] != 'complete': | |
| raise RuntimeError('Space did not complete all stages') | |
| scene = trimesh.load(model, force='scene', process=False) | |
| if len(scene.geometry) != manifest['metrics']['components']: | |
| raise RuntimeError('Downloaded component count differs from manifest') | |
| for mesh in scene.geometry.values(): | |
| if not len(mesh.faces) or mesh.visual.kind != 'texture' or mesh.visual.material.baseColorTexture is None: | |
| raise RuntimeError('Downloaded mesh has missing geometry or texture') | |
| with zipfile.ZipFile(bundle) as archive: | |
| embedded = json.loads(archive.read('manifest.json')) | |
| if embedded['id'] != manifest['id'] or 'final.glb' not in archive.namelist(): | |
| raise RuntimeError('Download archive does not match the completed run') | |
| print(json.dumps({'verified': True, 'run': manifest['id'], 'model': model, 'bundle': bundle, | |
| 'components': len(scene.geometry)}, indent=2)) | |
| if __name__ == '__main__': | |
| main() | |