Download tests/_helpers.py from Wiself/Voice: direct link, hf CLI and curl.
- Browser
- Download file 6.04 kB
-
https://huggingface.co/Wiself/Voice/resolve/main/tests/_helpers.py
- Command line
-
hf download hf://Wiself/Voice/tests/_helpers.py
-
curl -L -o _helpers.py https://huggingface.co/Wiself/Voice/resolve/main/tests/_helpers.py
6.04 kB
| """Shared fixtures for the voice product suite. Stdlib only. | |
| Top: unit + download tests run offline: python3 -m unittest discover -s tests | |
| Live: VOICE_TEST_LIVE=1 enables test_live/test_voices/test_e2e (real HF fetches). | |
| E2E: also needs a llama-cli binary (LLAMA_CLI or PATH); skips otherwise. | |
| """ | |
| import argparse | |
| import importlib.util | |
| import os | |
| import shutil | |
| import sys | |
| import tempfile | |
| import unittest | |
| from pathlib import Path | |
| os.environ.setdefault("VOICE_NO_VENV", "1") | |
| REPO_ROOT = Path(__file__).resolve().parent.parent | |
| VOICE_PY = REPO_ROOT / "voice.py" | |
| spec = importlib.util.spec_from_file_location("voice", str(VOICE_PY)) | |
| voice = importlib.util.module_from_spec(spec) | |
| sys.modules["voice"] = voice | |
| spec.loader.exec_module(voice) | |
| # Live fixtures: small, stable, public. | |
| CATGIRL_REPO = "xcx0902/Qwen3-1.7B-catgirl" # sharded safetensors finetune (the head) | |
| ABL_REPO = "DevQuasar/huihui-ai.Qwen3-1.7B-abliterated-GGUF" | |
| ABL_FILE = "huihui-ai.Qwen3-1.7B-abliterated.Q8_0.gguf" # quant head for passthrough | |
| BASE_REPO = "unsloth/Qwen3-1.7B-GGUF" | |
| BASE_FILE = "Qwen3-1.7B-UD-IQ2_XXS.gguf" # smallest full GGUF: cast target + runner | |
| LIVE = os.environ.get("VOICE_TEST_LIVE") == "1" | |
| def find_llama_cli(): | |
| # LLAMA_CLI env wins, then PATH. No machine paths: shippable anywhere. | |
| import shutil | |
| env = os.environ.get("LLAMA_CLI") | |
| if env and Path(env).is_file(): | |
| return env | |
| return shutil.which("llama-cli") | |
| LLAMA_CLI = find_llama_cli() | |
| needs_llama = unittest.skipUnless( | |
| LIVE and LLAMA_CLI, "needs VOICE_TEST_LIVE=1 and a llama-cli binary") | |
| def cache_dir(): | |
| d = Path(os.environ.get("VOICE_TEST_CACHE") or (Path.home() / ".cache" / "voice-tests")) | |
| d.mkdir(parents=True, exist_ok=True) | |
| return d | |
| def fetch_file(url, dest, label="", n_parts=8): | |
| """Full-file fetch through the product's own download_range (resumeable).""" | |
| dest = Path(dest) | |
| if dest.is_file() and dest.stat().st_size > 0: | |
| return dest | |
| import time | |
| import urllib.request | |
| last = None | |
| for attempt in range(6): | |
| req = urllib.request.Request(url, method="HEAD") | |
| try: | |
| with urllib.request.urlopen(req, timeout=60) as r: | |
| size = int(r.headers["Content-Length"]) | |
| etag = r.headers.get("ETag") | |
| break | |
| except urllib.error.HTTPError as e: | |
| last = e | |
| if e.code in (429, 500, 502, 503) and attempt < 5: | |
| time.sleep(voice._bounded_retry_after( | |
| getattr(e, "headers", None) or {}, 2.0 * (2 ** attempt), cap=60)) | |
| continue | |
| raise | |
| else: | |
| raise last | |
| part = dest.parent / (dest.name + ".parts") | |
| combined = voice.download_range(url, 0, size - 1, part, etag, label=label or dest.name, | |
| n_parts=n_parts) | |
| import shutil | |
| shutil.move(str(combined), str(dest)) | |
| return dest | |
| class IsolatedVoices(unittest.TestCase): | |
| """Each test gets a fresh VOICES_DIR; restored afterwards.""" | |
| def setUp(self): | |
| self._old = voice.VOICES_DIR | |
| self.vdir = Path(tempfile.mkdtemp(prefix="voices-")) | |
| voice.VOICES_DIR = self.vdir | |
| voice_ctx = sys.modules.get("vlib.ctx") | |
| if voice_ctx is not None: | |
| voice_ctx.VOICES_DIR = self.vdir | |
| # registry + reports + parts all derive from VOICES_DIR at call time, | |
| # except these module constants: repoint them too. | |
| self._old_reports = (voice.REPORTS_JSONL, voice.REPORTS_OUTBOX, voice.OPERATIONS_LOG, | |
| voice.HF_TOKEN_PATH) | |
| voice.REPORTS_JSONL = self.vdir / "reports.jsonl" | |
| voice.REPORTS_OUTBOX = self.vdir / "outbox" | |
| voice.OPERATIONS_LOG = self.vdir / "operations.log" | |
| voice.HF_TOKEN_PATH = self.vdir / ".hf_token" | |
| if voice_ctx is not None: | |
| voice_ctx.REPORTS_JSONL = voice.REPORTS_JSONL | |
| voice_ctx.REPORTS_OUTBOX = voice.REPORTS_OUTBOX | |
| voice_ctx.OPERATIONS_LOG = voice.OPERATIONS_LOG | |
| voice_ctx.HF_TOKEN_PATH = voice.HF_TOKEN_PATH | |
| def tearDown(self): | |
| voice.VOICES_DIR = self._old | |
| (voice.REPORTS_JSONL, voice.REPORTS_OUTBOX, voice.OPERATIONS_LOG, | |
| voice.HF_TOKEN_PATH) = self._old_reports | |
| voice_ctx = sys.modules.get("vlib.ctx") | |
| if voice_ctx is not None: | |
| voice_ctx.VOICES_DIR = self._old | |
| (voice_ctx.REPORTS_JSONL, voice_ctx.REPORTS_OUTBOX, voice_ctx.OPERATIONS_LOG, | |
| voice_ctx.HF_TOKEN_PATH) = self._old_reports | |
| shutil.rmtree(self.vdir, ignore_errors=True) | |
| def ns(**kw): | |
| a = dict(non_interactive=True, yes=True, verbose=False) | |
| a.update(kw) | |
| return argparse.Namespace(**a) | |
| def run_guarded(argv, timeout, **kw): | |
| """subprocess.run with a kill guarantee: no orphan survives a timeout, | |
| a KeyboardInterrupt, or a runner kill. Returns CompletedProcess; raises | |
| subprocess.TimeoutExpired (after reaping) or KeyboardInterrupt (clean).""" | |
| import signal | |
| import subprocess | |
| kw.setdefault("stdin", subprocess.DEVNULL) | |
| proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, | |
| text=True, **{k: v for k, v in kw.items() | |
| if k in ("stdin", "cwd", "env")}) | |
| try: | |
| out, err = proc.communicate(timeout=timeout) | |
| return subprocess.CompletedProcess(argv, proc.returncode, out, err) | |
| except subprocess.TimeoutExpired: | |
| proc.kill() | |
| try: | |
| out, err = proc.communicate(timeout=10) | |
| except subprocess.TimeoutExpired: | |
| proc.kill() | |
| out, err = proc.communicate() | |
| raise subprocess.TimeoutExpired(argv, timeout, out, err) | |
| except BaseException: | |
| # KeyboardInterrupt / runner death: take the child with us, then propagate | |
| try: | |
| proc.kill() | |
| except Exception: | |
| pass | |
| try: | |
| proc.wait(timeout=10) | |
| except Exception: | |
| pass | |
| raise | |