#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (c) 2025-2026 Renato Xavier da Silveira Rosa # See [LICENSE](./LICENSE) or [BSD-3-Clause-Clear](https://spdx.org/licenses/BSD-3-Clause-Clear.html) """Utilities for running vendored EPUB->TTS repositories in isolated venvs.""" import subprocess import sys import venv from pathlib import Path from typing import Optional def get_vendor_root() -> Path: return Path(__file__).resolve().parents[1] / "vendor" def get_repo_path(repo_name: str) -> Path: repo_path = get_vendor_root() / repo_name if not repo_path.exists(): raise FileNotFoundError( f"Vendored repository '{repo_name}' not found under {get_vendor_root()}" ) return repo_path def get_venv_path(repo_name: str) -> Path: return get_repo_path(repo_name) / ".venv" def get_venv_python(repo_name: str) -> Path: venv_path = get_venv_path(repo_name) python_executable = ( venv_path / "Scripts" / "python.exe" if sys.platform == "win32" else venv_path / "bin" / "python" ) if not python_executable.exists(): raise FileNotFoundError( f"Python executable not found in virtualenv at {python_executable}" ) return python_executable def ensure_venv(repo_name: str) -> Path: repo_path = get_repo_path(repo_name) venv_path = get_venv_path(repo_name) if not venv_path.exists(): venv.EnvBuilder(with_pip=True).create(venv_path) python_executable = get_venv_python(repo_name) subprocess.run( [str(python_executable), "-m", "pip", "install", "-e", str(repo_path)], check=True, ) return get_venv_python(repo_name) def build_run_command( repo_name: str, module_name: str, backend_cmd: Optional[str] = None, ) -> list[str]: if backend_cmd is None or backend_cmd == repo_name: python_executable = ensure_venv(repo_name) return [str(python_executable), "-m", module_name] return [backend_cmd]