Spaces:
Running
Running
| """Shared pytest fixtures for the img2threejs Space test suite.""" | |
| from __future__ import annotations | |
| import json | |
| import struct | |
| import sys | |
| import zlib | |
| from pathlib import Path | |
| import pytest | |
| REPO_ROOT = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(REPO_ROOT)) | |
| FIXTURES = Path(__file__).resolve().parent / "fixtures" | |
| def write_png(path: Path, w: int = 64, h: int = 64) -> Path: | |
| """Write a minimal valid RGB PNG with a gradient (no Pillow needed).""" | |
| raw = bytearray() | |
| for y in range(h): | |
| raw.append(0) | |
| for x in range(w): | |
| raw += bytes(((x * 4) % 256, (y * 4) % 256, ((x + y) * 2) % 256)) | |
| def chunk(tag: bytes, data: bytes) -> bytes: | |
| c = struct.pack(">I", len(data)) + tag + data | |
| return c + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF) | |
| ihdr = struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0) | |
| png = (b"\x89PNG\r\n\x1a\n" | |
| + chunk(b"IHDR", ihdr) | |
| + chunk(b"IDAT", zlib.compress(bytes(raw), 9)) | |
| + chunk(b"IEND", b"")) | |
| path.write_bytes(png) | |
| return path | |
| def ref_png_bytes() -> bytes: | |
| import tempfile | |
| with tempfile.TemporaryDirectory() as tmp: | |
| path = write_png(Path(tmp) / "ref.png") | |
| return path.read_bytes() | |
| def canned_spec() -> dict: | |
| return json.loads((FIXTURES / "canned_spec.json").read_text(encoding="utf-8")) | |
| def canned_spec_text() -> str: | |
| return (FIXTURES / "canned_spec.json").read_text(encoding="utf-8") | |
| class MockLLM: | |
| """Drop-in for app.llm.LLMClient returning queued canned replies. | |
| replies: list of strings returned in order (last one repeats). | |
| Records every call for assertions. | |
| """ | |
| def __init__(self, replies: list[str]) -> None: | |
| from app.llm import LLMResponse | |
| self._response_cls = LLMResponse | |
| self.replies = list(replies) | |
| self.calls: list[dict] = [] | |
| async def complete_vision(self, *, system: str, messages: list[dict]): | |
| self.calls.append({"system": system, "messages": messages}) | |
| index = min(len(self.calls) - 1, len(self.replies) - 1) | |
| return self._response_cls( | |
| text=self.replies[index], stop_reason="end_turn", style="anthropic") | |
| def make_settings(): | |
| """Build Settings instances from a controlled environment.""" | |
| from app.config import Settings | |
| def _make(**overrides): | |
| import os | |
| runs_dir = overrides.pop("runs_dir", "/tmp/i2t-test-runs") | |
| env = { | |
| "LLM_API_KEY": "test-key-not-real", | |
| "LLM_MODEL": "test-model", | |
| "LLM_BASE_URL": "https://llm.test/api", | |
| "RUNS_DIR": runs_dir, | |
| "GALLERY_DIR": overrides.pop( | |
| "gallery_dir", str(Path(runs_dir).parent / "gallery") | |
| ), | |
| } | |
| env.update({k: str(v) for k, v in overrides.items()}) | |
| old = {k: os.environ.get(k) for k in env} | |
| os.environ.update(env) | |
| try: | |
| return Settings() | |
| finally: | |
| for key, value in old.items(): | |
| if value is None: | |
| os.environ.pop(key, None) | |
| else: | |
| os.environ[key] = value | |
| return _make | |
| def factory_fixture_ts() -> Path: | |
| """tests/fixtures/factory_fixture.ts, regenerated through the real | |
| pipeline when missing (pure stdlib — always runnable).""" | |
| target = FIXTURES / "factory_fixture.ts" | |
| if not target.exists(): | |
| import subprocess | |
| proc = subprocess.run( | |
| [sys.executable, str(REPO_ROOT / "scripts" / "build_fixture_factory.py")], | |
| capture_output=True, text=True) | |
| assert proc.returncode == 0, f"fixture build failed:\n{proc.stdout}\n{proc.stderr}" | |
| return target | |