diff --git a/AGENTS.md b/AGENTS.md index a80feb5..0cf0a2c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -108,7 +108,7 @@ Website: `web/AGENTS.md`, `web/PRODUCT.md`, `web/DESIGN.md`. Do not duplicate si ## Dependencies (uv) -`uv.lock` is authoritative. `just lock` regenerates it, the hash-pinned `requirements/*.txt` exports, and `packaging/flatpak/python3-dependencies.yaml`. The AppImage build installs from `runtime`/`vad` plus `appimage.txt`; `install.sh` still resolves at install time (phase 2 of #701). **Do not edit `requirements/*.txt` by hand**, nor the url/sha256 pairs in `packaging/flatpak/python3-dependencies.yaml`. Change `pyproject.toml` (or `requirements/whisper.in` for the Whisper engine, `requirements/appimage*.in` for the AppImage), run `just lock`, and commit the lock plus the exports with the manifest change. +`uv.lock` is authoritative. `just lock` regenerates it, the hash-pinned `requirements/*.txt` exports, and `packaging/flatpak/python3-dependencies.yaml`. The AppImage build installs from `runtime`/`vad` plus `appimage.txt`; `install.sh` consumes the runtime and selected extras with `--require-hashes --no-deps --no-build-isolation`, then installs the project with `--no-deps --no-build-isolation`. **Do not edit `requirements/*.txt` by hand**, nor the url/sha256 pairs in `packaging/flatpak/python3-dependencies.yaml`. Change `pyproject.toml` (or `requirements/whisper.in` for the Whisper engine, `requirements/appimage*.in` for the AppImage), run `just lock`, and commit the lock plus the exports with the manifest change. | Constraint | Rule | |---|---| @@ -116,6 +116,9 @@ Website: `web/AGENTS.md`, `web/PRODUCT.md`, `web/DESIGN.md`. Do not duplicate si | `[vosk]` extra | Wheel-only on PyPI (no sdist). Never part of a source-buildable lock. `install.sh --engine=vosk` installs it | | Whisper CPU torch | `requirements/whisper.txt` is compiled from `requirements/whisper.in`. Pin `torch`/`torchaudio` together to `+cpu` local versions — PyPI CUDA wheels win resolution regardless of index order, and torchaudio lags torch on the CPU index | | pywhispercpp | Pinned in `install.sh` as `PYWHISPERCPP_VERSION` (keep in sync with `uv.lock`) | +| Installer build tools | `[dependency-groups].installer-build` exports to `requirements/installer-build.txt`. Bootstrap uses hashed wheels on new and reused venvs; source builds use these tools without build isolation. Its setuptools `<82` cap is for CPU torch only; do not add it to `[build-system]` (Arch). Backend rebuilds select pywhispercpp's complete hash block from `runtime.txt` via `scripts/installer_requirements.py`, with `--no-deps` so they cannot replace the runtime | +| Installer Whisper export | Compiled universally from Python 3.11, constrained by `runtime.txt` and `installer-build.txt` to keep shared pins consistent. Uses `+cpu` pins and best-match index resolution so the CPU index's older copies of shared packages do not downgrade the runtime | +| Remote installer | After cloning, hand off to the tagged `install.sh` with the original arguments and remote venv path. The installer and its exports must come from the same revision, including when the tag predates the pinned installer | | `[vad]` extra | `onnxruntime` for Silero VAD | | One export per extra | Every extra in `pyproject.toml` needs a hash-pinned `requirements/.txt` (underscores become dashes), written by a `uv export` line in `just lock`. `install.sh` installs six of them, so an extra with no export is an install path with nothing pinned, which is how `[parakeet]`, `[faster_whisper]` and `[vosk]` reached users. `tests/test_dependency_exports.py` enumerates the extras and the installer's call sites rather than trusting the recipe to stay complete; `docs` is the one exemption and it carries its reason in `EXPORT_EXEMPT` | | Exports match the lock | `just export-check` re-runs every `uv export` line in `just lock` and fails if a committed export is behind `uv.lock`. It reads those lines out of the recipe, so an export added there is checked without touching `scripts/check_exports.py`, and it runs under `UV_OFFLINE=1`: `uv export` reads the lock and nothing else. The lint job runs it, because an export named in the recipe and never regenerated is a snapshot, not a pin. `uv pip compile` targets are out of scope by design (they resolve against live indexes) | diff --git a/docs/INSTALL.md b/docs/INSTALL.md index d546338..55ba41a 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -32,6 +32,16 @@ The installer: - Downloads the default whisper.cpp tiny model (~74MB), verified against pinned checksums - Sets up desktop integration and launch wrappers +The source installer uses committed, hash-verified Python dependency exports, +including its pip and source-build tools. GTK/PyGObject still comes from your +distribution, and the venv retains access to system packages. A missing export +or unavailable pinned package causes that installation step to fail; the +existing optional-engine and VAD fallbacks still apply. + +Remote installs run the installer from the selected release tag. Older tags +therefore retain their original dependency-install behavior; downloading a new +bootstrap script does not change an older release's pins. + ### Installer modes ```bash diff --git a/install.sh b/install.sh index 9f1f33f..8fd3b13 100755 --- a/install.sh +++ b/install.sh @@ -6,6 +6,7 @@ # -e: exit on unhandled command failure -u: error on unset variables # -o pipefail: a pipeline fails if any stage fails set -Eeuo pipefail +INSTALLER_ARGS=("$@") # Exit codes (see --help). 1 remains the generic/unclassified failure. EXIT_OK=0 @@ -487,7 +488,27 @@ resolve_install_tag # Check if running from within the vocalinux repo or remotely (via curl) REPO_URL="https://github.com/VocaHQ/vocalinux.git" INSTALL_DIR="" -CLEANUP_ON_EXIT="no" +CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}" + +handoff_to_tagged_installer() { + local tagged_installer="$INSTALL_DIR/install.sh" + local remote_venv="$HOME/.local/share/vocalinux/venv" + + if grep -q 'CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}"' "$tagged_installer"; then + export VOCALINUX_REMOTE_INSTALL=yes + export TMPDIR="$(dirname "$VOCALINUX_TMP_DIR")" + rmdir "$VOCALINUX_TMP_DIR" + exec bash "$tagged_installer" "${INSTALLER_ARGS[@]}" "--venv-dir=$remote_venv" + fi + + bash "$tagged_installer" "${INSTALLER_ARGS[@]}" "--venv-dir=$remote_venv" || return $? + if [ ! -f "$INSTALL_DIR/activate-vocalinux.sh" ]; then + print_error "The tagged installer did not create activate-vocalinux.sh." + return 1 + fi + mkdir -p "$HOME/.local/bin" + mv "$INSTALL_DIR/activate-vocalinux.sh" "$HOME/.local/bin/activate-vocalinux.sh" +} # Function to check and install git if needed ensure_git_installed() { @@ -661,8 +682,10 @@ else CLEANUP_ON_EXIT="yes" print_info "Repository cloned to: $INSTALL_DIR" - # When running remotely, install venv to user's home directory - VENV_DIR="$HOME/.local/share/vocalinux/venv" + # Keep the installer and exports on the selected tag. Legacy tags do not + # understand the remote marker, so the handoff relocates their helper. + handoff_to_tagged_installer + exit "$EXIT_OK" fi # Change to install directory @@ -1767,7 +1790,8 @@ install_system_dependencies() { local APT_PACKAGES_DEBIAN_BASE="python3-pip python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-ibus-1.0 libcairo2-dev cmake python3-dev build-essential portaudio19-dev python3-venv pkg-config wget curl unzip vulkan-tools libvulkan-dev $VULKAN_SHADER_PKG xclip xsel wl-clipboard $PYWHISPERCPP_BUILD_DEPS" local APT_PACKAGES_DEBIAN_11_12="$APT_PACKAGES_DEBIAN_BASE libgirepository1.0-dev gir1.2-ayatanaappindicator3-0.1" local APT_PACKAGES_DEBIAN_13_PLUS="$APT_PACKAGES_DEBIAN_BASE libgirepository-2.0-dev gir1.2-ayatanaappindicator3-0.1" - local DNF_PACKAGES="python3-pip python3-gobject gtk3 ibus-devel gobject-introspection-devel python3-devel portaudio-devel python3-virtualenv pkg-config cmake wget curl unzip vulkan-tools vulkan-loader-devel glslc patchelf xclip xsel wl-clipboard" + # cairo-devel: the pinned pycairo builds from source; Fedora splits its headers/.pc out. + local DNF_PACKAGES="python3-pip python3-gobject gtk3 ibus-devel gobject-introspection-devel python3-devel portaudio-devel cairo-devel python3-virtualenv pkg-config cmake wget curl unzip vulkan-tools vulkan-loader-devel glslc patchelf xclip xsel wl-clipboard" local PACMAN_PACKAGES="python-pip python-gobject gtk3 ibus gobject-introspection python-cairo portaudio python-virtualenv pkg-config cmake wget curl unzip base-devel vulkan-tools vulkan-headers shaderc patchelf xclip xsel wl-clipboard" # ibus + typelib-1_0-IBus-1_0, not ibus-devel: the headers are not needed # (IBus is reached through GI at runtime), and requiring them pulls gtk-doc, @@ -2625,10 +2649,6 @@ setup_virtual_environment() { # Activate virtual environment source "$VENV_DIR/bin/activate" || { print_error "Failed to activate virtual environment"; exit "$EXIT_MISSING_DEPS"; } - # Update pip and setuptools - print_info "Updating pip, setuptools, and wheel..." - pip install --upgrade pip setuptools wheel || { print_error "Failed to update pip, setuptools, and wheel"; exit "$EXIT_NETWORK"; } - print_info "Virtual environment activated successfully." } @@ -2644,6 +2664,24 @@ fi # Set up virtual environment setup_virtual_environment +# Also run for reused venvs: setup_virtual_environment returns early for those. +# Wheels only here so bootstrapping cannot itself resolve unpinned build deps. +install_pinned_build_tools() { + local reqs_file="$INSTALL_DIR/requirements/installer-build.txt" + if [ ! -s "$reqs_file" ]; then + print_error "Missing or empty pinned requirements: $reqs_file" + return 1 + fi + print_info "Installing pinned pip and source-build tools..." + "$VENV_DIR/bin/python" -m pip install --require-hashes --no-deps \ + --only-binary=:all: --ignore-installed \ + -r "$reqs_file" --log "$VOCALINUX_TMP_DIR/bootstrap.log" +} +install_pinned_build_tools || { + print_error "Failed to install the pinned build tools. Check requirements/installer-build.txt." + exit "$EXIT_NETWORK" +} + # Create activation script for users # Put it in ~/.local/bin when running remotely, or current dir when running locally if [[ "$CLEANUP_ON_EXIT" == "yes" ]]; then @@ -2872,7 +2910,19 @@ install_cpu_pywhispercpp() { PYWHISPERCPP_CMAKE_ARGS=$(get_pywhispercpp_cmake_args) CMAKE_ARGS="${CMAKE_ARGS:+$CMAKE_ARGS }$PYWHISPERCPP_CMAKE_ARGS" \ - pip install --verbose --force-reinstall --no-cache-dir "pywhispercpp==${PYWHISPERCPP_VERSION}" --log "$PIP_LOG_FILE" + pip_reinstall_pywhispercpp "$PIP_LOG_FILE" +} + +pip_reinstall_pywhispercpp() { + local pip_log="$1" + shift + local reqs_file="$VOCALINUX_TMP_DIR/pywhispercpp.txt" + "$VENV_DIR/bin/python" "$INSTALL_DIR/scripts/installer_requirements.py" \ + "$INSTALL_DIR/requirements/runtime.txt" "$reqs_file" --package pywhispercpp || return 1 + # --no-deps preserves the locked runtime and avoids reinstalling numpy + # while replacing only the backend. Build tools were bootstrapped above. + "$VENV_DIR/bin/python" -m pip install --require-hashes --no-deps --no-build-isolation \ + --verbose --force-reinstall --no-cache-dir -r "$reqs_file" --log "$pip_log" "$@" } is_pywhispercpp_installed() { @@ -3028,7 +3078,7 @@ install_whispercpp_with_gpu_support() { print_info "Installing pywhispercpp ($GPU_BACKEND backend)..." if CMAKE_ARGS="${CMAKE_ARGS:+$CMAKE_ARGS }$PYWHISPERCPP_CMAKE_ARGS" \ GGML_VULKAN=1 \ - pip install --verbose --force-reinstall --no-cache-dir --no-binary pywhispercpp "pywhispercpp==${PYWHISPERCPP_VERSION}" --log "$PIP_LOG_FILE" 2>&1; then + pip_reinstall_pywhispercpp "$PIP_LOG_FILE" --no-binary pywhispercpp 2>&1; then if verify_pywhispercpp_backend_install "$GPU_BACKEND"; then GPU_INSTALL_SUCCESS=true else @@ -3054,7 +3104,7 @@ install_whispercpp_with_gpu_support() { print_info "Installing pywhispercpp ($GPU_BACKEND backend)..." if CMAKE_ARGS="${CMAKE_ARGS:+$CMAKE_ARGS }$PYWHISPERCPP_CMAKE_ARGS $CUDA_CMAKE_ARGS" \ GGML_CUDA=1 \ - pip install --verbose --force-reinstall --no-cache-dir --no-binary pywhispercpp "pywhispercpp==${PYWHISPERCPP_VERSION}" --log "$PIP_LOG_FILE" 2>&1; then + pip_reinstall_pywhispercpp "$PIP_LOG_FILE" --no-binary pywhispercpp 2>&1; then if verify_pywhispercpp_backend_install "$GPU_BACKEND"; then GPU_INSTALL_SUCCESS=true else @@ -3191,49 +3241,9 @@ FALLBACK_VOSK_CONFIG echo "" } -# Distro python3-gi provides `gi`, but apt does not drop pip-visible -# PyGObject dist-info. `pip install .` then tries to build pygobject from -# sdist and dies (needs girepository-2.0). Same skip as uv export's -# --no-emit-package pygobject: install the other deps, then the project -# with --no-deps. Do not use requirements/*.txt hashes here (Phase 2). -write_pip_reqs_skip_pygobject() { - local dest="$1" - shift - "$VENV_DIR/bin/python" - "$dest" "$@" <<'PY' -from pathlib import Path -import re -import sys - -dest = Path(sys.argv[1]) -extras = sys.argv[2:] -text = Path("pyproject.toml").read_text() - - -def quoted_strings(block: str): - return re.findall(r'"([^"]+)"', block) - - -reqs = [] -if not extras: - match = re.search(r"^dependencies = \[(.*?)\]", text, re.M | re.S) - for req in quoted_strings(match.group(1) if match else ""): - pkg = re.split(r"[<>=!~;\[]", req, 1)[0].strip() - if pkg.lower() == "pygobject": - continue - reqs.append(req) -else: - opt = re.search( - r"^\[project\.optional-dependencies\](.*?)(\n\[|\Z)", text, re.M | re.S - ) - opt_text = opt.group(1) if opt else "" - for extra in extras: - match = re.search(rf"^{re.escape(extra)} = \[(.*?)\]", opt_text, re.M | re.S) - if match: - reqs.extend(quoted_strings(match.group(1))) - -dest.write_text("\n".join(reqs) + ("\n" if reqs else "")) -PY -} +# Exports use --no-emit-package pygobject: distro GI remains visible through +# --system-site-packages. Install the locked dependencies first, then the local +# project with --no-deps and --no-build-isolation so neither step re-resolves. require_distro_gi() { if ! "$VENV_DIR/bin/python" -c "import gi" 2>/dev/null; then @@ -3248,25 +3258,33 @@ pip_install_reqs_file() { local pip_log="$1" local reqs_file="$2" if [ ! -s "$reqs_file" ]; then - return 0 + print_error "Missing or empty pinned requirements: $reqs_file" + return 1 fi - pip install -r "$reqs_file" --log "$pip_log" + "$VENV_DIR/bin/python" -m pip install --require-hashes --no-deps --no-build-isolation \ + -r "$reqs_file" --log "$pip_log" } pip_install_project_skip_pygobject() { local pip_log="$1" shift - require_distro_gi - write_pip_reqs_skip_pygobject "$VOCALINUX_TMP_DIR/runtime-deps.txt" - pip_install_reqs_file "$pip_log" "$VOCALINUX_TMP_DIR/runtime-deps.txt" || return 1 - pip install --no-deps --log "$pip_log" "$@" + require_distro_gi || return 1 + pip_install_reqs_file "$pip_log" "$INSTALL_DIR/requirements/runtime.txt" || return 1 + "$VENV_DIR/bin/python" -m pip install --no-deps --no-build-isolation --log "$pip_log" "$@" } pip_install_extras_skip_pygobject() { local pip_log="$1" shift - write_pip_reqs_skip_pygobject "$VOCALINUX_TMP_DIR/extra-deps.txt" "$@" - pip_install_reqs_file "$pip_log" "$VOCALINUX_TMP_DIR/extra-deps.txt" + local extra + for extra in "$@"; do + # uv normalizes underscores to dashes in export filenames. + case "$extra" in + vad|vosk|parakeet|faster_whisper|whisper|dev) ;; + *) print_error "Unknown dependency extra: $extra"; return 1 ;; + esac + pip_install_reqs_file "$pip_log" "$INSTALL_DIR/requirements/${extra//_/-}.txt" || return 1 + done } # Function to install Python package with error handling and verification @@ -3340,13 +3358,13 @@ PY # Install test dependencies print_info "Installing test dependencies..." - pip install pytest pytest-mock pytest-cov --log "$PIP_LOG_FILE" || { + pip_install_extras_skip_pygobject "$PIP_LOG_FILE" dev || { print_warning "Failed to install some test dependencies. Tests may not run correctly." } # Install all optional dependencies for development print_info "Installing all optional dependencies for development..." - pip_install_extras_skip_pygobject "$PIP_LOG_FILE" whisper dev || { + pip_install_extras_skip_pygobject "$PIP_LOG_FILE" whisper || { print_warning "Failed to install some optional dependencies." print_warning "Some features may not work correctly." } @@ -3384,25 +3402,16 @@ PY local WHISPER_INSTALL_SUCCESS=false - # Install PyTorch and whisper - print_info "Installing PyTorch..." - if pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu --log "$PIP_LOG_FILE" 2>&1; then - print_success "PyTorch installed successfully" - - print_info "Installing openai-whisper..." - if pip install openai-whisper --log "$PIP_LOG_FILE" 2>&1; then - # Verify the installation by importing the module - if "$VENV_DIR/bin/python" -c "import whisper" 2>/dev/null; then - WHISPER_INSTALL_SUCCESS=true - print_success "Whisper installed and verified successfully" - else - print_error "Whisper package installed but import failed" - fi + print_info "Installing pinned Whisper and CPU PyTorch..." + if pip_install_extras_skip_pygobject "$PIP_LOG_FILE" whisper; then + if "$VENV_DIR/bin/python" -c "import whisper" 2>/dev/null; then + WHISPER_INSTALL_SUCCESS=true + print_success "Whisper installed and verified successfully" else - print_error "Failed to install openai-whisper package" + print_error "Whisper package installed but import failed" fi else - print_error "Failed to install PyTorch" + print_error "Failed to install pinned Whisper dependencies" fi if [[ "$WHISPER_INSTALL_SUCCESS" == "true" ]]; then @@ -3586,10 +3595,9 @@ PARAKEET_CONFIG print_info "╚════════════════════════════════════════════════════════╝" print_info "" - # Ensure requests library is installed - print_info "Installing requests library..." - pip install requests --log "$PIP_LOG_FILE" || { - print_error "Failed to install requests library" + # requests is already installed from the runtime export. + "$VENV_DIR/bin/python" -c "import requests" || { + print_error "The pinned requests library is not importable" return 1 } print_success "requests library installed" @@ -4530,7 +4538,8 @@ run_tests() { # Check if pytest is installed in the virtual environment if ! "$VENV_DIR/bin/python" -c "import pytest" &>/dev/null; then print_info "Installing pytest and related packages..." - pip install pytest pytest-mock pytest-cov || { + local PIP_LOG_FILE="$VOCALINUX_TMP_DIR/test-deps.log" + pip_install_extras_skip_pygobject "$PIP_LOG_FILE" dev || { print_error "Failed to install pytest. Cannot run tests." return 1 } diff --git a/justfile b/justfile index ef997f5..2583804 100644 --- a/justfile +++ b/justfile @@ -151,6 +151,7 @@ verify-release tag="": # when you want newer CPU builds (torchaudio on the CPU index lags torch). lock: uv lock + uv export --only-group installer-build --no-emit-project -o requirements/installer-build.txt uv export --no-dev --no-emit-project --no-emit-package pygobject -o requirements/runtime.txt uv export --no-dev --extra vad --no-emit-project --no-emit-package pygobject -o requirements/vad.txt # One export per selectable engine. install.sh installs each of these as an @@ -168,7 +169,8 @@ lock: uv pip compile requirements/whisper.in --generate-hashes --emit-index-url \ --index-url https://pypi.org/simple \ --extra-index-url https://download.pytorch.org/whl/cpu \ - --python-platform x86_64-unknown-linux-gnu -o requirements/whisper.txt + --index-strategy unsafe-best-match --universal --python-version 3.11 \ + -c requirements/runtime.txt -c requirements/installer-build.txt -o requirements/whisper.txt # Compiled rather than exported: what the AppImage bundles on top of the # lock, and what builds it, are pinned away from uv.lock on purpose -- # see requirements/appimage.in. --universal so one file covers both arches. diff --git a/pyproject.toml b/pyproject.toml index b9944d4..bd56018 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,20 @@ docs = [ # --only-group lint` installs them without the project, so the lint job needs # no portaudio/girepository headers to build pyaudio and PyGObject. [dependency-groups] +# install.sh installs this wheel-only toolchain before any source builds, then +# disables build isolation so pip cannot resolve another unpinned environment. +installer-build = [ + "pip>=25.3,<27", + # CPU torch still requires pkg_resources; this cap applies only to the + # installer venv, not build-system.requires used by Arch's toolchain. + "setuptools>=77,<82", + "wheel", + "meson-python>=0.16", + "cmake==3.31.10", + "ninja==1.13.0", + "repairwheel", + "setuptools-scm>=8", +] lint = [ "black>=23.0.0", "isort>=5.12.0", diff --git a/requirements/installer-build.txt b/requirements/installer-build.txt new file mode 100644 index 0000000..86c6cb3 --- /dev/null +++ b/requirements/installer-build.txt @@ -0,0 +1,109 @@ +# This file was autogenerated by uv via the following command: +# uv export --only-group installer-build --no-emit-project -o requirements/installer-build.txt +altgraph==0.17.5 \ + --hash=sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7 \ + --hash=sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597 + # via macholib +cmake==3.31.10 \ + --hash=sha256:1debc3a0823ce5d8d1bc17154599bbbb337c2681f93622b618bc78f46576e42a \ + --hash=sha256:2f766bb46367e5e0559fa33184653754bce044583a06014dcaebf8e6dff8a1f1 \ + --hash=sha256:3c17bb24dba15f8ecc3fd706afe04264410ef88796f4115c119327c961d5dc57 \ + --hash=sha256:422a54711aa977af19d59b8f6010354cdda0b72a2e6d702b6d892e3e2cdf98a2 \ + --hash=sha256:4cefb0a28ac1268b4eed4b595bf3aaff8de9704089066027700ec36584eccab8 \ + --hash=sha256:678fc23db37cc69f01e18eb28790450ecc9401fd2fcd43364cc18f92330c12c2 \ + --hash=sha256:6970bb75c4dfc28cc31ff0cd848194d09094ae00d605181e1345b2ff70b61050 \ + --hash=sha256:7c300e4ae68fbc1414a85505f7feb262cee82ff3304a286885ebf803b11a997c \ + --hash=sha256:8d2ec5fc45d305227020c82213140a51a0cebe3c84f0299036f05716b3a52f60 \ + --hash=sha256:91410816db3beefe2f6032d721f9978c98dc7646e9992c0325486597164fab81 \ + --hash=sha256:a4a5615f31f692c9b9aa8b365704e4b76172348af6fa40e16fea3f118bb01194 \ + --hash=sha256:a7864605238759a4ae8e3bd1fda2bb03978e3e37df310852662dcf53866413c8 \ + --hash=sha256:ad697643a00d9ba85179590a383c4f7401169b55ebf4b8b2938daf28c6bdeb6d \ + --hash=sha256:b059a1810a2ce766b3e531bdc8d730bc192e260a9fa7dec7a0eb7a053d6063c7 \ + --hash=sha256:b331984de38dbda22d676f8812c8905526341ba7b397fe8c359255ff4d051193 \ + --hash=sha256:c2e5361dea9754ed3b06cf834894fb47dcbe7036d5e5d87acaeb10ff3dd5fd10 \ + --hash=sha256:e135d5f1e59f1dc1c80eea87321977d6c0eff86cb601c28e0965a1dd457ea587 \ + --hash=sha256:ec3d14a0e72e401b3665034dc37901df17f0b4e9c5b163be6cfedfb93470ac0f \ + --hash=sha256:f1ea1fe826355560e8976c3d5794d9357444209bc0e0d56676c71e6a571fd474 +delvewheel==1.13.1 \ + --hash=sha256:1b3bc696193a57e322b8bfd644de240be6e003066aae44cc3d5aef8cbee22ca3 \ + --hash=sha256:ae445f35f411c367f5b350431ac5f1435af8128bff31ccf34035a409704da8c6 + # via repairwheel +macholib==1.16.4 \ + --hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \ + --hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362 + # via repairwheel +meson==1.12.0 \ + --hash=sha256:71f133147fa0fcfe8f4df49fa1045771064947834538409e5d97b3613aac8b4e \ + --hash=sha256:88afe0c20e52030218924ac37d0c81c59b4b5f3ae3752c8c6d7470c7d365886c + # via meson-python +meson-python==0.21.1 \ + --hash=sha256:270bc9b78957c47e0aa1758ad616dba3f943d8f9cbdb944d318c3c1c7a49e4bd \ + --hash=sha256:78b3345dcbc0fed7b939e7e37a9faab35bddaae07bf62e7542c8ad479c395af5 +ninja==1.13.0 \ + --hash=sha256:11be2d22027bde06f14c343f01d31446747dbb51e72d00decca2eb99be911e2f \ + --hash=sha256:1c97223cdda0417f414bf864cfb73b72d8777e57ebb279c5f6de368de0062988 \ + --hash=sha256:3c0b40b1f0bba764644385319028650087b4c1b18cdfa6f45cb39a3669b81aa9 \ + --hash=sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630 \ + --hash=sha256:3d7d7779d12cb20c6d054c61b702139fd23a7a964ec8f2c823f1ab1b084150db \ + --hash=sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978 \ + --hash=sha256:4be9c1b082d244b1ad7ef41eb8ab088aae8c109a9f3f0b3e56a252d3e00f42c1 \ + --hash=sha256:5f8e1e8a1a30835eeb51db05cf5a67151ad37542f5a4af2a438e9490915e5b72 \ + --hash=sha256:60056592cf495e9a6a4bea3cd178903056ecb0943e4de45a2ea825edb6dc8d3e \ + --hash=sha256:6739d3352073341ad284246f81339a384eec091d9851a886dfa5b00a6d48b3e2 \ + --hash=sha256:8cfbb80b4a53456ae8a39f90ae3d7a2129f45ea164f43fadfa15dc38c4aef1c9 \ + --hash=sha256:aa45b4037b313c2f698bc13306239b8b93b4680eb47e287773156ac9e9304714 \ + --hash=sha256:b4f2a072db3c0f944c32793e91532d8948d20d9ab83da9c0c7c15b5768072200 \ + --hash=sha256:be7f478ff9f96a128b599a964fc60a6a87b9fa332ee1bd44fa243ac88d50291c \ + --hash=sha256:d741a5e6754e0bda767e3274a0f0deeef4807f1fec6c0d7921a0244018926ae5 \ + --hash=sha256:e8bad11f8a00b64137e9b315b137d8bb6cbf3086fbdc43bf1f90fd33324d2e96 \ + --hash=sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1 \ + --hash=sha256:fb46acf6b93b8dd0322adc3a4945452a4e774b75b91293bafcc7b7f8e6517dfa \ + --hash=sha256:fb8ee8719f8af47fed145cced4a85f0755dd55d45b2bddaf7431fa89803c5f3e +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via + # meson-python + # pyproject-metadata + # repairwheel + # setuptools-scm + # vcs-versioning + # wheel +pefile==2024.8.26 \ + --hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \ + --hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f + # via + # delvewheel + # repairwheel +pip==26.2.1 \ + --hash=sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e \ + --hash=sha256:f6ad667e89a1fe78046c8f13232b247200f5258d7828f3f7883d660878e0813f +pyelftools==0.33 \ + --hash=sha256:660d82dcbeb8e83d1702bd97f223f761625da06111c0cc988eac6b8ab0c1b61f \ + --hash=sha256:f215ad5f47d3f1373a21496a6c9e0707c622840d0622f23ff7ce08678b020036 + # via repairwheel +pyproject-metadata==0.12.1 \ + --hash=sha256:8809a4df6fe08279b39a8890669506ed3158e0617855ac9aff098fcbe772ae4c \ + --hash=sha256:f7162d580a96386a8eb096da06215f981f547d1490f03055ef99e323bc2da427 + # via meson-python +repairwheel==0.7.0 \ + --hash=sha256:46083dad76e35595712ae593c1c9f112fb3f37a0e63268906e6de8182de55122 \ + --hash=sha256:7fff43ed5abbf9710ef5ea6478c10cfd551aae043f445fd46307d4b602674ce0 +setuptools==81.0.0 \ + --hash=sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a \ + --hash=sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6 + # via setuptools-scm +setuptools-scm==10.2.3 \ + --hash=sha256:7fcf8ff55c95eb8b572a23c81495e5559b9b90f3e82fcf0952bb76c37de27a81 \ + --hash=sha256:f179ed3e2a63cf5823e5ee9aa9ca08386219400443a0553224d72dde3f206b44 +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 + # via repairwheel +vcs-versioning==2.4.1 \ + --hash=sha256:b7089ec9bef67b2cad82148366e8eac4d63173f440ec62628282b59eb96bbcb0 \ + --hash=sha256:d4575de3115ec9434393c87c80ffb0eb98a16056bfe2b11ce0f3a97aff67fe0a + # via setuptools-scm +wheel==0.48.0 \ + --hash=sha256:3217dcc807155e45db462d7ef2431f5ddda0d7273b700d05a67b271ceb1287ab \ + --hash=sha256:94800765601e9171bf5d58d066e640662842bcedcbab982b2c90787a2c987322 diff --git a/requirements/whisper.in b/requirements/whisper.in index 043819f..9facf55 100644 --- a/requirements/whisper.in +++ b/requirements/whisper.in @@ -4,6 +4,9 @@ # CUDA-bundled PyPI wheels can never match, regardless of index order. # Bump these pins together in step with each other when regenerating # (`just lock`). +# Resolve across supported Python versions and constrain shared packages to +# runtime.txt / installer-build.txt; otherwise this export can downgrade the +# runtime (or select a numpy requiring a newer Python than the installer). # # The extra-index line below propagates into whisper.txt so plain # `pip install -r requirements/whisper.txt` resolves against the CPU index. diff --git a/requirements/whisper.txt b/requirements/whisper.txt index 3d8d98d..653576f 100644 --- a/requirements/whisper.txt +++ b/requirements/whisper.txt @@ -1,14 +1,195 @@ # This file was autogenerated by uv via the following command: -# uv pip compile requirements/whisper.in --generate-hashes --emit-index-url --index-url https://pypi.org/simple --extra-index-url https://download.pytorch.org/whl/cpu --python-platform x86_64-unknown-linux-gnu -o requirements/whisper.txt +# uv pip compile requirements/whisper.in --generate-hashes --emit-index-url --index-url https://pypi.org/simple --extra-index-url https://download.pytorch.org/whl/cpu --index-strategy unsafe-best-match --universal --python-version 3.11 -c requirements/runtime.txt -c requirements/installer-build.txt -o requirements/whisper.txt --index-url https://pypi.org/simple --extra-index-url https://download.pytorch.org/whl/cpu -certifi==2022.12.7 \ - --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 - # via requests -charset-normalizer==2.1.1 \ - --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f - # via requests +certifi==2026.7.22 \ + --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ + --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 + # via + # -c requirements/runtime.txt + # requests +charset-normalizer==3.5.1 \ + --hash=sha256:00668ebb0609751758682eb0b5857e7c35b9f00e84dfdef062e103244ec94d45 \ + --hash=sha256:012a22b88a77ca2e59b98ac5889b0deb604147666032f45e6d6e217634d2550d \ + --hash=sha256:01e93745f7f219b703b60ba7afead36cfc4242782be5af484673fc500df12da5 \ + --hash=sha256:04368edf83514385ffc3e1cfd4546e595f4f1272dd23ba437a93a9cc3741d47b \ + --hash=sha256:0722590aabf9dc6a6c0343d523c05458fa2b5047dbe6302fd526bb570600753f \ + --hash=sha256:07ffd07412fc5d5e84cd8952acf9ff7e4ed7a708e69d1bada19d8ba91711353f \ + --hash=sha256:09a7bba9f739468c8e78c36a75c33768e53cb1959fc638f510454c14683f00d5 \ + --hash=sha256:0b2b1b3fa5670c127b246df1d0c059defd41f689a868a3b9d79df9b1cac42d22 \ + --hash=sha256:0c6dfb5ca6723eeed15aa8e564a014d69fcb8812f94eef11fe3631e0508199f5 \ + --hash=sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac \ + --hash=sha256:13e3afe97712e8887cd516e960c63f0b93122971e5b5e4b2622fe7701771e838 \ + --hash=sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90 \ + --hash=sha256:195ce897c6153c0700078142cf8efe3e6454ca4cf4357499e4078dfd83396626 \ + --hash=sha256:19a3dd5aa73cef1c99687c4fc57db016a9c17104ae1185da88ba566a5d3bebe4 \ + --hash=sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369 \ + --hash=sha256:1f5883d77fd409a261abb5dc8ccbe335720d798b1de4abb3b1d47ccbbc76b53b \ + --hash=sha256:21b82d8082f6f5e7f456ef0bd16323d08de1266efbfeb476e64b2a91d1471a4e \ + --hash=sha256:252d099029bcbea642f2a06c4ed5046bdf8b5a8150b64afa5e027e88b106e5ee \ + --hash=sha256:256dd4d85d9e4dc595e2bc983c980e73f62ddeb3165c58b4c3dfe78c5c8548c1 \ + --hash=sha256:26422d45fd13551cf564c58932f7d72b4f58b93b0fcf18c35ba6be12b46bb102 \ + --hash=sha256:2679de311c7946dde5d3b6f44941844133ff5c7cb86099c0061ab1e8901c20a8 \ + --hash=sha256:29880d17a8eb0b5cfdfd8944b468322928059aa35f1f5fa8ff22b149ec0b42f8 \ + --hash=sha256:2bced4061f000f7187254a02ad3433ae17eaf991747ceea2f478422590a5bba9 \ + --hash=sha256:2e9cf9253119d8e5d111f05d71626786fd3d6193817316eab1ca088cdb8593cf \ + --hash=sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0 \ + --hash=sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031 \ + --hash=sha256:329fc3ccb63ad22d867d84c2adea759a64079a37ba4a343433b02c7a2816871e \ + --hash=sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235 \ + --hash=sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072 \ + --hash=sha256:35aea775dc2bd5f54cd84a1cd2696cc3207c479cb9cf0bd346f0d343e4300ddb \ + --hash=sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c \ + --hash=sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950 \ + --hash=sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2 \ + --hash=sha256:366ec70f5547c640d3ce1985722490f23faf4eb5216a7eeba78277490e78dacb \ + --hash=sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e \ + --hash=sha256:3d27167433c0d5f18dc850f07d0b3816221984fecdc405d6c157a6f0b8f8e9e6 \ + --hash=sha256:3e5e1224c0a6a90e05843e07adfec669edebec17801c67072f51e59561d63c0b \ + --hash=sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2 \ + --hash=sha256:433c5a81eade63b47e522303bad236f59dba55ea6951746f5558355eeed8c75d \ + --hash=sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa \ + --hash=sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2 \ + --hash=sha256:494b70049a4d69aec6e8137c13af4cf8db8c9f9820a1392ac293b0dd2987a818 \ + --hash=sha256:496846868fea80e479324862fa877f02411f2fd0f83b79ccee2607aa68b2a032 \ + --hash=sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71 \ + --hash=sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96 \ + --hash=sha256:4bea7f8ebe90bbd7f0e4a2de42ca6924ba23e3e76418c408ff82f1d46fabd687 \ + --hash=sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8 \ + --hash=sha256:4c9548dc78002099910abaebc0a72ac58b7d30931869e0351c09b507dff4ece3 \ + --hash=sha256:4d26f14f041e83dd8edfd61f4cd4fa7285d31798b5bf1f28e70c367ba6c41d61 \ + --hash=sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9 \ + --hash=sha256:52ec005752a56ae79547a05c0139ca2501a0c866390b6115008456b9f0e7cde1 \ + --hash=sha256:55261ac0d2941c42f196dd576f543d87a8ee03cd6f5e30dfb4d807b2e3b9121a \ + --hash=sha256:56490c595a28b1bb27dfc583e816152a9767721ef58b2c03b13f954d2f707420 \ + --hash=sha256:58d3e12c88e0950bca850ae1f7c256055c097639c2edb9eb123af9807d8b15e4 \ + --hash=sha256:58d4aa13a59c969dbfdf9e6a9560e242cbfd9e8a8f50c2747714df1a423adf65 \ + --hash=sha256:59171c6e45bf07d0d5cab3b0bf81d945035530f6873398b3b531c31184d46663 \ + --hash=sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f \ + --hash=sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591 \ + --hash=sha256:5c84bec0ab5ae0c64bfe73a7d2adcb5ce73b467523fc27fd6a28ab2aa6cbe35a \ + --hash=sha256:5ca0555312ae2fe82715cada7fac375530c2f3349e1eaa1bcb33d0283ac79a18 \ + --hash=sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e \ + --hash=sha256:5e2d0e146dcb57034f8b97dc58d2d512cb90aba253960ce449f695fec6a82c6f \ + --hash=sha256:5fc45d653ea8c9a20479167e11d4a0f8cb2fa3470737ab6f9c827532313187b7 \ + --hash=sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3 \ + --hash=sha256:6199d5606e2bbf2b096cf64d03f8b6790c91081d5ac866b8e7bb6422738cc60c \ + --hash=sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3 \ + --hash=sha256:687c9ca3035544b113bea2055e180af96fb63c0c476e22a9180f51925186e7b7 \ + --hash=sha256:6b7430cf5728e68f6c462254009a6ef4086e1bea43cf2f57aa9c55fb4f50ff96 \ + --hash=sha256:6ba32c4d2abf1d2fe7cf27d280f4cca5664233b0f885549c7761719eb977f486 \ + --hash=sha256:6c9cdde8becb25a7fde49924511aa2644d6f8081cc8df8e9452724303348d8e3 \ + --hash=sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6 \ + --hash=sha256:6e2912d4babbc65196ac13c2f53468dc57fb8b9c25ef913e8c59ddf7c6dc0e1b \ + --hash=sha256:6e5e4d73d588ca5ed09df1b7dcd1b203d1df3c542e3f50d126c947d432b10731 \ + --hash=sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959 \ + --hash=sha256:706bfd38730a5ac7a365793269a00f4e988178cec121391f4248d84ad8c972e9 \ + --hash=sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf \ + --hash=sha256:774d157f112367ff4abd29019f38f023c24e00e56edc7829c20e358a5a913ad8 \ + --hash=sha256:77efcff2b23071c349402ac1066667a3d011f62398d81408c9b88ad991747c9e \ + --hash=sha256:789b8982559ae28dad2356519f841655756cdcd96616410590ae0b17454ee64f \ + --hash=sha256:7ac76cf9afd34929d76eb7fcb63be476a4853d8a96f0dcf2d0db68a0cbdf9885 \ + --hash=sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0 \ + --hash=sha256:823f82903d189af463d7df250ef1f7f696f3cee08cc8d91deb565e8d425f6506 \ + --hash=sha256:838648accb3a7fd9803fd45c87bce8509648eb0c11bc34e216141300977244f2 \ + --hash=sha256:854066be00447fa8de2ccbbe893e2ffc4b123ef16d897af794c1e18bd4a714b0 \ + --hash=sha256:85d5855daafc240cc045c026d7a15fd198a09b0fc8ff6f5ecbb5297b509cb11e \ + --hash=sha256:85de3134b5379856e323ba37c19c9256d39425f7b76a63af52b09fb4664c2e8f \ + --hash=sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e \ + --hash=sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491 \ + --hash=sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a \ + --hash=sha256:8ac8c94b6539074e0f40899301273ac8402b9b3e01c7b7ba269ff30340aaaf20 \ + --hash=sha256:8fe532b3c966d1fb794e0698e4589d0444017ae77fc0b31edea13c0e35bcc449 \ + --hash=sha256:9085f87b0e38a2b92b8923059b4e8789fe40d9279712d15dcc670048d77079af \ + --hash=sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c \ + --hash=sha256:92caef967d287a407085d61176fce4012b1dd62daed4eb6d5ceb26d3d2538712 \ + --hash=sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7 \ + --hash=sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a \ + --hash=sha256:94fbf1c0c6cc0d3d5e50f9a9313a8cdca90dd696d34b381cd1704f8c9e939f20 \ + --hash=sha256:950f23cb393f85543777b0433f082cddd25b51ab398eac7971146495679efe5f \ + --hash=sha256:96eefc178f8636b9c760c5829345307fd81cfae9ab1e80997dbddeb0f54ee9a3 \ + --hash=sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9 \ + --hash=sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e \ + --hash=sha256:978eab16f55b4ab2c2a745be9a0a840bf8f09a7f227d9c76eb30214d078865a5 \ + --hash=sha256:994e883d17c559cdfd38c84003c8b27d25424a1077272a17e7cd27bfe0bf57b2 \ + --hash=sha256:9ac4444d8d4fd4c4bd08bf451ed3167aa9e7ec6cdb41b648794f1d1103652e36 \ + --hash=sha256:9b5db6052055d34d41230fb78d7c439c23dc536a9896f6cb039e8dd92cfc1263 \ + --hash=sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4 \ + --hash=sha256:9dbdd9205662134957cf0c324f639bdc5031c0ca056e2369e238db75187c0f11 \ + --hash=sha256:9eea3ab2597a5e65fe65296e2d6a84570845a6b55532d90333d740d48bbc850a \ + --hash=sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3 \ + --hash=sha256:a3a370082ce34d0612f421e15fe011c53bb1feff21a26d06ad4fb244dab5a375 \ + --hash=sha256:a545775cfe815855ea32d7c27731d79da358ef2055b4a25830231b1622dd18aa \ + --hash=sha256:a5cbd90ecf0fc62e64726917ad083b73001f0563657a87ec3c0b504e277dc90d \ + --hash=sha256:a6d095662e73e74f0a49988e0593373e243e3a52e27bfeea0a859e88acf4a0f5 \ + --hash=sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99 \ + --hash=sha256:a951ad59cad9145664a730d3036b40b844e74d2d3683da40111463cd3a83845d \ + --hash=sha256:aa1099b956fb795e686d073568f6dc002a0bb89765ea6d5b055dd7d9bf1b116c \ + --hash=sha256:aa2bb0b37202dca27175591f761108b5d34096ade1191ffe4808bdf6b1571488 \ + --hash=sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6 \ + --hash=sha256:ab743e9bc90c1f73552ec33e10e3331315acd2c397b36065b591b0181de533cc \ + --hash=sha256:ac00177c4831ffa650f8609e4bdddd5fe09c03b1c0c47acece7e6ea20421598b \ + --hash=sha256:ac13b004224fb341e1e25a1ed5e19d32f57cdb2a403e01f003b46f051a550f6f \ + --hash=sha256:acaf604462bf330b0d07e7a07c1d6e4adac79e5fb13e9c5140590542cafacc00 \ + --hash=sha256:ae31a1a1db2ee6cc2942fccaf695c934bc7f3db9f2133a3fef1f367cf1a4ab10 \ + --hash=sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598 \ + --hash=sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6 \ + --hash=sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962 \ + --hash=sha256:b54e7e13267d49ffbfe68e25b3cbd774dab38fa37238f71265e91b36146eb21c \ + --hash=sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08 \ + --hash=sha256:ba2f37ee79e6338845261a3c5b1784e5d1acdff2c0785b284f1b633033d136ab \ + --hash=sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573 \ + --hash=sha256:baf3775a2635e5a11fbd5e4e64ee69c7e86875d224a5c72aca4c141064589a90 \ + --hash=sha256:bb57753e36e4855b8ca375069482250a6246372331a3e4f3407eaebb007443f5 \ + --hash=sha256:bd6c173f04743d483881bffa1478d5a4624475b8cd1d2194956a75548e191c18 \ + --hash=sha256:be47f99644b208bff7766314013f9acf57b056b04191d570d68ad14022cf5b1d \ + --hash=sha256:c010f5581d9c612804cc59fcf7b524b707fbcb72828551237ab545bb5c7034af \ + --hash=sha256:c1dcc36dcb96abc02236e182d17e0f71430152a6c2c7447421da2d2dc144edea \ + --hash=sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c \ + --hash=sha256:c658c50ac0c98cd755a2dd50b7977d3bca7df401dcc47fbdfa87db53ef7d4e8b \ + --hash=sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6 \ + --hash=sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8 \ + --hash=sha256:cc0329df4caaceb950d2f580b5ac716a377f7059624a0bafaeaf8a218c6ed774 \ + --hash=sha256:cc5d36d96478aa9c60654bd932525bf32964c62a7281eafdf16d85003a8d6004 \ + --hash=sha256:ce854f5f478050ade5a238731c4ca985a7d3b3cb53ff600a9b5c3b689b5f0a7a \ + --hash=sha256:ced3fdd71aaa83ce593746c2edb42b7a59cb4c19c8b5c407781c72e493aae55a \ + --hash=sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2 \ + --hash=sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2 \ + --hash=sha256:d1ee1e296209fdce05b81b663250eefa02213a2da7b41bf26f7829b8ba3545aa \ + --hash=sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe \ + --hash=sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3 \ + --hash=sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc \ + --hash=sha256:e06efa066f7dbadbc84ebc126a97c452a6451dfcf589d89d788484949e1cf795 \ + --hash=sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d \ + --hash=sha256:e4b018dc5a0eee4676e38fe84a47a427816c590b93b55d9025274ec4d6ffc2dc \ + --hash=sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893 \ + --hash=sha256:e71c909f353863b2b89c83de2ebed71ea6d0df8a6ef65a128193c5e650766bef \ + --hash=sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d \ + --hash=sha256:e9fbdce1e47394b09bc9f26ab117dfc8d6491977a11d86f592bb42c779db2fda \ + --hash=sha256:eb12fb2ba69ffa05f8695f61c69e591dc4b4a12ac3757ac8af8adb259bf56d17 \ + --hash=sha256:eda059b6bc8bc0812d626fd91a7ce01bf583df0a61296eff390fd94141a34e30 \ + --hash=sha256:f03ac127268b43ef4fe9e6ab6794a6794b49485a0cc0c1db79876d2f33f75bc7 \ + --hash=sha256:f298e218441525d3794428b4c8b8fb8662c6d3ea79925d4807ee6b9a96a3bca5 \ + --hash=sha256:f5542f9b941279d82d41eb0aa9f98eba36fe4df5c7086c651df7944935b37182 \ + --hash=sha256:f6f7deae3feb4edfa2efaf7c574fe88cbf055038a6abdb40188e4fff66d5699f \ + --hash=sha256:f9b1e28d0e8dbfa858abdba91d6b547beaf2df1a59bec6da6faae7b96a4991a9 \ + --hash=sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada \ + --hash=sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876 \ + --hash=sha256:fb78f6e7fcd8ad785d28cd577168bc1aaee827b25bb8755638f694794ea98f0a \ + --hash=sha256:fbc597639158fd7c14d55e808718848319540f51b0e6746e3eefa59723a4a348 \ + --hash=sha256:fce8cbd4997efeb450bd298b54f755dcdff18d496f7a5ddbb4867c6d7c88fdc3 \ + --hash=sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f \ + --hash=sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0 \ + --hash=sha256:fdb8a068947befafba9952162645dc2fecaeb400e64584829ed5e9b2fbe21a7f + # via + # -c requirements/runtime.txt + # requests +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via + # -c requirements/runtime.txt + # tqdm filelock==3.32.3 \ --hash=sha256:0ffa185a3540854c95caa7fa76b76cb219d907415e2c5dc9af25fd970563487f \ --hash=sha256:7f0ca4bcc0e181c60dbbd8aa9ab5b120ebb99e4e064e83636340056f833a1f09 @@ -17,9 +198,12 @@ fsspec==2026.7.0 \ --hash=sha256:b57ddbafedfaef7018c1ecab32aa200a9d7ca26b77965f64e48b70061249d279 \ --hash=sha256:c803c40f4cf860b49dea58ee3e1c33cb9c790520e233537e1340049f89b82a88 # via torch -idna==3.4 \ - --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 - # via requests +idna==3.19 \ + --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ + --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 + # via + # -c requirements/runtime.txt + # requests jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 @@ -183,7 +367,84 @@ numba==0.67.0 \ --hash=sha256:f63d43db06b4756424d6d2484737c902e0ae944a0eec3e8b0b4de2c695b15caa \ --hash=sha256:f99f880ff25f418a67f9a1d00d0ddfbc63430f627b523e515085a592a7567f4b # via openai-whisper -numpy==2.5.2 \ +numpy==2.4.6 ; python_full_version < '3.12' \ + --hash=sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1 \ + --hash=sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4 \ + --hash=sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f \ + --hash=sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079 \ + --hash=sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096 \ + --hash=sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47 \ + --hash=sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66 \ + --hash=sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d \ + --hash=sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1 \ + --hash=sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e \ + --hash=sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147 \ + --hash=sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd \ + --hash=sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75 \ + --hash=sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063 \ + --hash=sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73 \ + --hash=sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab \ + --hash=sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4 \ + --hash=sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41 \ + --hash=sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402 \ + --hash=sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698 \ + --hash=sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 \ + --hash=sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8 \ + --hash=sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b \ + --hash=sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8 \ + --hash=sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0 \ + --hash=sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662 \ + --hash=sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91 \ + --hash=sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0 \ + --hash=sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f \ + --hash=sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3 \ + --hash=sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f \ + --hash=sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67 \ + --hash=sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6 \ + --hash=sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997 \ + --hash=sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b \ + --hash=sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e \ + --hash=sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538 \ + --hash=sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627 \ + --hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 \ + --hash=sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02 \ + --hash=sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853 \ + --hash=sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c \ + --hash=sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43 \ + --hash=sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd \ + --hash=sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 \ + --hash=sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089 \ + --hash=sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778 \ + --hash=sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1 \ + --hash=sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb \ + --hash=sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 \ + --hash=sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb \ + --hash=sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a \ + --hash=sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8 \ + --hash=sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359 \ + --hash=sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5 \ + --hash=sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7 \ + --hash=sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751 \ + --hash=sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8 \ + --hash=sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605 \ + --hash=sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e \ + --hash=sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45 \ + --hash=sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2 \ + --hash=sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895 \ + --hash=sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe \ + --hash=sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb \ + --hash=sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a \ + --hash=sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577 \ + --hash=sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d \ + --hash=sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a \ + --hash=sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda \ + --hash=sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6 \ + --hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20 + # via + # -c requirements/runtime.txt + # numba + # openai-whisper +numpy==2.5.2 ; python_full_version >= '3.12' \ --hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \ --hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \ --hash=sha256:07d4e89f3a9ab0a9ba24264ccdb642b3dd951b2281e8883a5481a4aa79cc31a7 \ @@ -251,6 +512,7 @@ numpy==2.5.2 \ --hash=sha256:f06571a052127dc1b4e8b83029b4d1b20daa2b64a31cdd181fc6bc774e9000eb \ --hash=sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f # via + # -c requirements/runtime.txt # numba # openai-whisper openai-whisper==20250625 \ @@ -372,12 +634,18 @@ regex==2026.7.19 \ --hash=sha256:fe31f28c94402043161876a258a9c6f757cb485905c7614ce8d6cd40e6b7bdc1 \ --hash=sha256:ffd8893ccc1c2fce6e0d6ca402d716fe1b29db70c7132609a05955e31b2aa8f2 # via tiktoken -requests==2.28.1 \ - --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 - # via tiktoken -setuptools==78.1.0 \ - --hash=sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8 - # via torch +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via + # -c requirements/runtime.txt + # tiktoken +setuptools==81.0.0 \ + --hash=sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a \ + --hash=sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6 + # via + # -c requirements/installer-build.txt + # torch sympy==1.14.0 \ --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \ --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 @@ -503,10 +771,13 @@ torchaudio==2.11.0+cpu \ --hash=sha256:fa0c22f58f60c3537b7d28ed2501e0995acb2a65d9af2708f21edaad67186cd8 \ --hash=sha256:fae220128cbfe060c663fbb2a1967b88c605f9eb49b535903cca694011662534 # via -r requirements/whisper.in -tqdm==4.66.5 \ - --hash=sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd - # via openai-whisper -triton==3.7.1 \ +tqdm==4.70.0 \ + --hash=sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220 \ + --hash=sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953 + # via + # -c requirements/runtime.txt + # openai-whisper +triton==3.7.1 ; (platform_machine == 'x86_64' and sys_platform == 'linux') or sys_platform == 'linux2' \ --hash=sha256:10ba85fa2cca4a2fbdeb36bf1cb082f2c252bda55bf9fccd74f65ec5bc647e68 \ --hash=sha256:2020153b08280415ec0da6607834e79166442147e78e144df06b508c75b186d2 \ --hash=sha256:3daf64305d6cea88d3334c65ebc9bcd0c64c9564a977084366aa768d57cbcf64 \ @@ -523,7 +794,12 @@ triton==3.7.1 \ typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 - # via torch -urllib3==1.26.13 \ - --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc - # via requests + # via + # -c requirements/installer-build.txt + # torch +urllib3==2.7.0 \ + --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ + --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 + # via + # -c requirements/runtime.txt + # requests diff --git a/scripts/installer_requirements.py b/scripts/installer_requirements.py new file mode 100644 index 0000000..7587e00 --- /dev/null +++ b/scripts/installer_requirements.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +"""Select committed requirement blocks without changing pins, markers or hashes. + +The installer uses complete exports for normal installs and just pywhispercpp's +block for backend rebuilds. Missing exports or packages are errors, never an +empty successful install. Only the standard library is needed before bootstrap. +""" + +from __future__ import annotations + +import argparse +import re +from pathlib import Path + + +def select_requirements(source: Path, package: str | None = None) -> str: + """Return an export, optionally retaining only one distribution's blocks.""" + text = source.read_text(encoding="utf-8") + blocks = re.split(r"(?=^[A-Za-z0-9_.-]+==)", text, flags=re.MULTILINE) + requirements = blocks[1:] + if not requirements: + raise ValueError(f"No pinned requirements in {source}") + if package is not None: + normalize = lambda name: re.sub(r"[-_.]+", "-", name).lower() + requirements = [ + block + for block in requirements + if normalize(block.split("==", 1)[0]) == normalize(package) + ] + if not requirements: + raise ValueError(f"No pin for {package} in {source}") + return blocks[0] + "".join(requirements) + + +def main() -> None: + """Write the selected export to the installer's scratch directory.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("source", type=Path) + parser.add_argument("destination", type=Path) + parser.add_argument("--package") + args = parser.parse_args() + try: + text = select_requirements(args.source, args.package) + except (OSError, ValueError) as error: + parser.exit(1, f"Cannot install pinned dependencies: {error}\n") + args.destination.write_text(text, encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/tests/test_installer_pinned_dependencies.py b/tests/test_installer_pinned_dependencies.py new file mode 100644 index 0000000..c63c56e --- /dev/null +++ b/tests/test_installer_pinned_dependencies.py @@ -0,0 +1,349 @@ +"""Exercise pinned installer calls, including fail-closed and rebuild paths.""" + +from __future__ import annotations + +import hashlib +import importlib.util +import json +import os +import re +import shlex +import subprocess +import sys +import tomllib +import zipfile +from pathlib import Path + +import pytest +from packaging.requirements import Requirement + +ROOT = Path(__file__).resolve().parents[1] +INSTALLER = ROOT / "install.sh" +SELECTOR = ROOT / "scripts/installer_requirements.py" + + +def _run(tmp_path: Path, command: str, *, fail_pip: bool = False) -> subprocess.CompletedProcess: + """Run real shell helpers with a recording interpreter in a path with spaces.""" + venv = tmp_path / "test venv" + (venv / "bin").mkdir(parents=True) + python = venv / "bin/python" + python.write_text( + f"#!{sys.executable}\n" + "import json, os, subprocess, sys\n" + "if sys.argv[1:3] == ['-m', 'pip']:\n" + " with open(os.environ['PIP_CALLS'], 'a') as log:\n" + " log.write(json.dumps(sys.argv[3:]) + '\\n')\n" + " sys.exit(int(os.environ.get('FAIL_PIP', '0')))\n" + f"sys.exit(subprocess.call([{sys.executable!r}, *sys.argv[1:]]))\n" + ) + python.chmod(0o755) + functions = [ + "pip_install_reqs_file", + "pip_install_project_skip_pygobject", + "pip_install_extras_skip_pygobject", + "pip_reinstall_pywhispercpp", + "install_cpu_pywhispercpp", + "get_pywhispercpp_cmake_args", + "install_pinned_build_tools", + ] + source = "\n".join( + f"source <(sed -n '/^{name}() {{$/,/^}}$/p' {shlex.quote(str(INSTALLER))})" + for name in functions + ) + script = f""" +set -euo pipefail +print_error() {{ echo "$*" >&2; }} +print_info() {{ :; }} +require_distro_gi() {{ :; }} +VENV_DIR={shlex.quote(str(venv))} +INSTALL_DIR={shlex.quote(str(ROOT))} +VOCALINUX_TMP_DIR={shlex.quote(str(tmp_path))} +{source} +{command} +""" + return subprocess.run( + ["bash", "-c", script], + env={**os.environ, "PIP_CALLS": str(tmp_path / "calls"), "FAIL_PIP": str(int(fail_pip))}, + capture_output=True, + text=True, + timeout=10, + ) + + +def _calls(tmp_path: Path) -> list[list[str]]: + path = tmp_path / "calls" + return [json.loads(line) for line in path.read_text().splitlines()] if path.exists() else [] + + +@pytest.mark.parametrize("extra", ["vad", "vosk", "parakeet", "faster_whisper", "whisper", "dev"]) +def test_extras_use_committed_hashes(tmp_path: Path, extra: str) -> None: + result = _run(tmp_path, f'pip_install_extras_skip_pygobject "install log" {extra}') + assert result.returncode == 0, result.stderr + (call,) = _calls(tmp_path) + assert {"--require-hashes", "--no-deps", "--no-build-isolation"} <= set(call) + assert call[call.index("-r") + 1] == str(ROOT / f"requirements/{extra.replace('_', '-')}.txt") + + +@pytest.mark.parametrize("editable", [False, True]) +def test_project_follows_locked_runtime_without_resolution(tmp_path: Path, editable: bool) -> None: + args = '-e "project directory"' if editable else '"project directory"' + result = _run(tmp_path, f"pip_install_project_skip_pygobject log {args}") + assert result.returncode == 0, result.stderr + runtime, project = _calls(tmp_path) + assert runtime[runtime.index("-r") + 1].endswith("/requirements/runtime.txt") + assert "--require-hashes" in runtime + assert {"--no-deps", "--no-build-isolation"} <= set(project) + assert ("-e" in project) == editable + assert project[-1] == "project directory" + + +def test_failed_dependencies_never_install_project(tmp_path: Path) -> None: + result = _run(tmp_path, "pip_install_project_skip_pygobject log .", fail_pip=True) + assert result.returncode != 0 + assert len(_calls(tmp_path)) == 1 + + +@pytest.mark.parametrize("kind", ["missing", "empty", "unknown-extra"]) +def test_missing_pins_fail_before_pip(tmp_path: Path, kind: str) -> None: + path = tmp_path / "missing.txt" + if kind == "empty": + path.touch() + command = ( + "pip_install_extras_skip_pygobject log typo" + if kind == "unknown-extra" + else f"pip_install_reqs_file log {shlex.quote(str(path))}" + ) + result = _run(tmp_path, command) + assert result.returncode != 0 + assert not _calls(tmp_path) + + +@pytest.mark.parametrize("backend", ["cpu", "vulkan", "cuda"]) +def test_rebuild_uses_only_locked_pywhispercpp(tmp_path: Path, backend: str) -> None: + command = ( + "install_cpu_pywhispercpp log" + if backend == "cpu" + else f"GGML_{backend.upper()}=1 pip_reinstall_pywhispercpp log --no-binary pywhispercpp" + ) + result = _run(tmp_path, command) + assert result.returncode == 0, result.stderr + (call,) = _calls(tmp_path) + assert {"--require-hashes", "--no-deps", "--no-build-isolation", "--force-reinstall"} <= set( + call + ) + selected = (tmp_path / "pywhispercpp.txt").read_text() + assert re.findall(r"^([\w.-]+)==", selected, re.M) == ["pywhispercpp"] + lock = tomllib.loads((ROOT / "uv.lock").read_text()) + package = next(p for p in lock["package"] if p["name"] == "pywhispercpp") + assert f"pywhispercpp=={package['version']}" in selected + for artifact in [package["sdist"], *package["wheels"]]: + assert artifact["hash"] in selected + + +def test_bootstrap_uses_only_hashed_wheels(tmp_path: Path) -> None: + result = _run(tmp_path, "install_pinned_build_tools") + assert result.returncode == 0, result.stderr + (call,) = _calls(tmp_path) + assert {"--require-hashes", "--only-binary=:all:", "--ignore-installed", "--no-deps"} <= set( + call + ) + + +@pytest.mark.parametrize("kind", ["missing", "empty"]) +def test_bootstrap_rejects_missing_or_empty_export(tmp_path: Path, kind: str) -> None: + """Reject missing pins before invoking pip, including in a conditional.""" + requirements = tmp_path / "requirements" + requirements.mkdir() + export = requirements / "installer-build.txt" + if kind == "empty": + export.touch() + result = _run( + tmp_path, + f"INSTALL_DIR={shlex.quote(str(tmp_path))}\n" "install_pinned_build_tools || exit 23", + ) + assert result.returncode == 23, result.stdout + result.stderr + assert f"Missing or empty pinned requirements: {export}" in result.stderr + assert not _calls(tmp_path) + + +@pytest.mark.parametrize("remote_aware", [False, True]) +def test_remote_handoff_preserves_tagged_behavior(tmp_path: Path, remote_aware: bool) -> None: + """A main bootstrap must preserve remote behavior for every tag.""" + clone = tmp_path / "old tagged tree" + clone.mkdir() + marker = 'CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}"\n' if remote_aware else "" + (clone / "install.sh").write_text( + "#!/bin/bash\n" + + marker + + 'printf "%s\\n" "${VOCALINUX_REMOTE_INSTALL:-no}" "$PWD" "$@"\n' + + "helper=activate-vocalinux.sh\n" + + 'if [ "${VOCALINUX_REMOTE_INSTALL:-no}" = yes ]; then\n' + + ' mkdir -p "$HOME/.local/bin"\n' + + ' helper="$HOME/.local/bin/activate-vocalinux.sh"\n' + + "fi\n" + + 'printf helper > "$helper"\n' + ) + scratch = tmp_path / "scratch" + scratch.mkdir() + text = INSTALLER.read_text() + start = text.index("handoff_to_tagged_installer() {") + end = text.index("\n}", start) + 2 + handoff = text[start:end] + home = tmp_path / "home" + home.mkdir() + result = subprocess.run( + [ + "bash", + "-c", + f"set -eu\n{handoff}\ncd {shlex.quote(str(clone))}\n" + f"INSTALL_DIR={shlex.quote(str(clone))}\n" + f"VOCALINUX_TMP_DIR={shlex.quote(str(scratch))}\n" + "INSTALLER_ARGS=(--auto --tag=v0.17.0 --engine=remote_api)\n" + 'print_error() { echo "$*" >&2; }\n' + "handoff_to_tagged_installer", + ], + env={**os.environ, "HOME": str(home)}, + capture_output=True, + text=True, + timeout=10, + ) + assert result.returncode == 0, result.stderr + assert result.stdout.splitlines() == [ + "yes" if remote_aware else "no", + str(clone), + "--auto", + "--tag=v0.17.0", + "--engine=remote_api", + f"--venv-dir={home}/.local/share/vocalinux/venv", + ] + assert scratch.exists() != remote_aware + helper = home / ".local/bin/activate-vocalinux.sh" + assert helper.read_text() == "helper" + assert not (clone / "activate-vocalinux.sh").exists() + + +def test_every_pip_install_has_an_explicit_resolution_boundary() -> None: + """Catch a new engine adding a bare pip install outside the shared helpers.""" + source = INSTALLER.read_text().replace("\\\n", " ") + installs = [ + line.strip() + for line in source.splitlines() + if re.match(r'^\s*(?:pip |"\$VENV_DIR/bin/python" -m pip )install ', line) + ] + assert len(installs) >= 4 + for line in installs: + assert "--no-deps" in line, line + if "--require-hashes" in line: + assert "--no-build-isolation" in line or "--only-binary=:all:" in line, line + else: + assert '--log "$pip_log" "$@"' in line, line # the local project only + assert "--no-build-isolation" in line, line + + +def test_selector_preserves_python_markers_and_rejects_absent_package(tmp_path: Path) -> None: + spec = importlib.util.spec_from_file_location("installer_requirements", SELECTOR) + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + source = ROOT / "requirements/runtime.txt" + selected = module.select_requirements(source, "numpy") + assert "python_full_version < '3.12'" in selected + assert "python_full_version >= '3.12'" in selected + assert selected.count("numpy==") == 2 + with pytest.raises(ValueError, match="No pin"): + module.select_requirements(source, "typo") + + +@pytest.mark.parametrize("minor", [11, 12, 13, 14]) +def test_whisper_does_not_replace_runtime_or_build_pins(minor: int) -> None: + environment = { + "python_version": f"3.{minor}", + "python_full_version": f"3.{minor}.0", + "sys_platform": "linux", + "platform_machine": "x86_64", + } + + def pins(name: str) -> dict[str, str]: + result = {} + for line in (ROOT / f"requirements/{name}.txt").read_text().splitlines(): + if re.match(r"^[\w.-]+==", line): + requirement = Requirement(line.rstrip(" \\")) + if requirement.marker is None or requirement.marker.evaluate(environment): + result[requirement.name] = str(requirement.specifier) + return result + + base = pins("runtime") | pins("installer-build") + whisper = pins("whisper") + assert whisper["torch"].endswith("+cpu") + for name in base.keys() & whisper.keys(): + assert base[name] == whisper[name], name + + +@pytest.mark.timeout(60) +@pytest.mark.parametrize("tamper", [False, True]) +def test_real_pip_checks_hash_before_install(tmp_path: Path, tamper: bool) -> None: + """Use a local wheel and no index: exercise pip, not a mocked hash checker.""" + venv = tmp_path / "venv" + subprocess.run([sys.executable, "-m", "venv", "--system-site-packages", str(venv)], check=True) + wheel = tmp_path / "pinned_fixture-1.0-py3-none-any.whl" + with zipfile.ZipFile(wheel, "w") as archive: + archive.writestr("pinned_fixture.py", "VALUE = 1\n") + archive.writestr( + "pinned_fixture-1.0.dist-info/METADATA", + "Metadata-Version: 2.1\nName: pinned-fixture\nVersion: 1.0\n", + ) + archive.writestr( + "pinned_fixture-1.0.dist-info/WHEEL", + "Wheel-Version: 1.0\nGenerator: test\nRoot-Is-Purelib: true\nTag: py3-none-any\n", + ) + archive.writestr("pinned_fixture-1.0.dist-info/RECORD", "") + digest = hashlib.sha256(wheel.read_bytes()).hexdigest() + if tamper: + with zipfile.ZipFile(wheel, "a") as archive: + archive.writestr("tampered.txt", "changed bytes") + requirements = tmp_path / "requirements.txt" + requirements.write_text(f"pinned-fixture==1.0 --hash=sha256:{digest}\n") + source = ( + f"source <(sed -n '/^pip_install_reqs_file() {{$/,/^}}$/p' {shlex.quote(str(INSTALLER))})" + ) + result = subprocess.run( + [ + "bash", + "-c", + f'{source}\nVENV_DIR={shlex.quote(str(venv))}\nprint_error() {{ echo "$*" >&2; }}\npip_install_reqs_file {shlex.quote(str(tmp_path / "pip.log"))} {shlex.quote(str(requirements))}', + ], + env={ + **os.environ, + "PIP_NO_INDEX": "1", + "PIP_FIND_LINKS": str(tmp_path), + "PIP_DISABLE_PIP_VERSION_CHECK": "1", + }, + capture_output=True, + text=True, + timeout=30, + ) + assert (result.returncode != 0) == tamper, result.stdout + result.stderr + if tamper: + assert "HASHES" in result.stderr + + +def test_source_built_runtime_packages_have_build_deps_on_split_devel_distros() -> None: + """The pinned runtime builds these from source; distro lists that split + -devel packages must carry their build deps.""" + runtime = (ROOT / "requirements/runtime.txt").read_text(encoding="utf-8") + installer = INSTALLER.read_text(encoding="utf-8") + + def package_line(prefix: str) -> str: + return next(line for line in installer.splitlines() if f"local {prefix}=" in line) + + build_deps = { + "pycairo": ("cairo-devel", "libcairo2-dev"), + "pyaudio": ("portaudio-devel", "portaudio19-dev"), + "evdev": ("python3-devel", "python3-dev"), + } + for name, (dnf_pkg, apt_pkg) in build_deps.items(): + if not re.search(rf"^{name}==", runtime, re.MULTILINE): + continue # wheels-only or dropped: nothing to build + assert dnf_pkg in package_line("DNF_PACKAGES"), name + assert apt_pkg in package_line("APT_PACKAGES_UBUNTU"), name + assert apt_pkg in package_line("APT_PACKAGES_DEBIAN_BASE"), name diff --git a/tests/test_installer_review_notes.py b/tests/test_installer_review_notes.py index e6abfce..00f2b57 100644 --- a/tests/test_installer_review_notes.py +++ b/tests/test_installer_review_notes.py @@ -2,8 +2,6 @@ import os import subprocess -import sys -import tomllib from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] @@ -64,9 +62,8 @@ def test_system_dep_and_venv_failures_use_structured_exit_codes() -> None: in source ) assert 'exit "$EXIT_MISSING_DEPS"' in source - assert ( - 'print_error "Failed to update pip, setuptools, and wheel"; exit "$EXIT_NETWORK"' in source - ) + bootstrap_failure = source.split("install_pinned_build_tools || {", 1)[1].split("}", 1)[0] + assert 'exit "$EXIT_NETWORK"' in bootstrap_failure assert ( 'print_error "Failed to install Vocalinux package. Installation cannot continue."' in source ) @@ -90,7 +87,7 @@ def test_whispercpp_fallback_installs_vosk_extra() -> None: def test_project_pip_install_skips_pygobject() -> None: source = _installer_source() - assert "write_pip_reqs_skip_pygobject()" in source + assert "write_pip_reqs_skip_pygobject()" not in source assert "pip_install_project_skip_pygobject()" in source assert "pip install --no-deps" in source assert "--no-emit-package pygobject" in source @@ -101,46 +98,6 @@ def test_project_pip_install_skips_pygobject() -> None: assert 'pip install -e ".[whisper,dev]"' not in source -def _run_reqs_writer(dest: Path, *extras: str) -> None: - source = _installer_source() - start = source.index("from pathlib import Path\nimport re\nimport sys\n") - end = source.index("\nPY\n}", start) - result = subprocess.run( - [sys.executable, "-", str(dest), *extras], - check=False, - cwd=INSTALLER.parent, - input=source[start:end], - capture_output=True, - text=True, - ) - assert result.returncode == 0, result.stderr - - -def test_write_pip_reqs_skip_pygobject_runtime(tmp_path) -> None: - dest = tmp_path / "runtime.txt" - _run_reqs_writer(dest) - reqs = dest.read_text().splitlines() - assert reqs - assert all("pygobject" not in req.lower() for req in reqs) - assert any(req.startswith("pyaudio") for req in reqs) - assert any(req.startswith("pywhispercpp") for req in reqs) - - -def test_write_pip_reqs_skip_pygobject_vosk_extra(tmp_path) -> None: - """The writer copies an extra's specifiers through, bounds and all. - - Read out of pyproject.toml rather than written here as a literal. This - assertion was `["vosk>=0.3.45"]` and failed the day the extra gained an - upper bound, reporting an intentional pyproject edit as an installer defect. - """ - with PYPROJECT.open("rb") as handle: - expected = tomllib.load(handle)["project"]["optional-dependencies"]["vosk"] - assert expected, "the vosk extra declares nothing; this would compare [] to []" - dest = tmp_path / "vosk.txt" - _run_reqs_writer(dest, "vosk") - assert dest.read_text().splitlines() == expected - - def test_settings_uses_engine_flag_not_removed_with_whisper() -> None: text = SETTINGS.read_text(encoding="utf-8") assert "./install.sh --engine=whisper" in text diff --git a/uv.lock b/uv.lock index d668140..b9e9fea 100644 --- a/uv.lock +++ b/uv.lock @@ -2,9 +2,12 @@ version = 1 revision = 3 requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.15'", - "python_full_version >= '3.12' and python_full_version < '3.15'", - "python_full_version < '3.12'", + "python_full_version >= '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.15' and sys_platform == 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform == 'ios'", + "python_full_version < '3.12' and sys_platform != 'ios'", + "python_full_version < '3.12' and sys_platform == 'ios'", ] [[package]] @@ -16,6 +19,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] +[[package]] +name = "altgraph" +version = "0.17.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/f8/97fdf103f38fed6792a1601dbc16cc8aac56e7459a9fff08c812d8ae177a/altgraph-0.17.5.tar.gz", hash = "sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7", size = 48428, upload-time = "2025-11-21T20:35:50.583Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl", hash = "sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597", size = 21228, upload-time = "2025-11-21T20:35:49.444Z" }, +] + [[package]] name = "anyio" version = "4.15.1" @@ -440,6 +452,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, ] +[[package]] +name = "cmake" +version = "3.31.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/7b/fbadb3f4fe90ad6ef57f9f5f9e4f721af8e86376fbdf11da2c6ed099830e/cmake-3.31.10.tar.gz", hash = "sha256:ec3d14a0e72e401b3665034dc37901df17f0b4e9c5b163be6cfedfb93470ac0f", size = 34499, upload-time = "2025-11-20T17:07:54.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/3b/6ed408a99709808df4014bead522e075f0e8d1100e6d886eb5bc30fee04e/cmake-3.31.10-py3-none-macosx_10_10_universal2.whl", hash = "sha256:ad697643a00d9ba85179590a383c4f7401169b55ebf4b8b2938daf28c6bdeb6d", size = 48001731, upload-time = "2025-11-20T17:06:57.473Z" }, + { url = "https://files.pythonhosted.org/packages/ad/59/acc2f79180d8aaf55b707ee65b5296ae76a3295ebff9e65d840849b6abc0/cmake-3.31.10-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c300e4ae68fbc1414a85505f7feb262cee82ff3304a286885ebf803b11a997c", size = 27579802, upload-time = "2025-11-20T17:07:00.676Z" }, + { url = "https://files.pythonhosted.org/packages/cc/0a/2f17b5cc0d3ac1ce2324364c044d170d06167f8d6b7464ee76857114d95e/cmake-3.31.10-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c17bb24dba15f8ecc3fd706afe04264410ef88796f4115c119327c961d5dc57", size = 26832178, upload-time = "2025-11-20T17:07:03.475Z" }, + { url = "https://files.pythonhosted.org/packages/b1/6c/d629c3b6a30105f5946e754b42d6ce84be36c190cc70b70fb2eb8a0ffc37/cmake-3.31.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4a5615f31f692c9b9aa8b365704e4b76172348af6fa40e16fea3f118bb01194", size = 27165148, upload-time = "2025-11-20T17:07:06.895Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d8/9842811ec5615598003499e2d38062d42651a20d022f93f9a590807d76b3/cmake-3.31.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d2ec5fc45d305227020c82213140a51a0cebe3c84f0299036f05716b3a52f60", size = 28889720, upload-time = "2025-11-20T17:07:09.597Z" }, + { url = "https://files.pythonhosted.org/packages/01/e9/7042b018121ceaae48416d37edb9924646e3cc8bbb417374cafdf8c2fa58/cmake-3.31.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7864605238759a4ae8e3bd1fda2bb03978e3e37df310852662dcf53866413c8", size = 30757069, upload-time = "2025-11-20T17:07:12.537Z" }, + { url = "https://files.pythonhosted.org/packages/24/a8/4e320cd6dfae630c5d9532d822c20a095565bcb159be839919ff7ea2952f/cmake-3.31.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1debc3a0823ce5d8d1bc17154599bbbb337c2681f93622b618bc78f46576e42a", size = 26932214, upload-time = "2025-11-20T17:07:16.075Z" }, + { url = "https://files.pythonhosted.org/packages/f4/2e/cefc60143950ca1a8dda26d4c8484e6fc406db16e7ca098ebae549de35f9/cmake-3.31.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f766bb46367e5e0559fa33184653754bce044583a06014dcaebf8e6dff8a1f1", size = 27808794, upload-time = "2025-11-20T17:07:18.974Z" }, + { url = "https://files.pythonhosted.org/packages/1f/55/3f7d68d03f116142ce1076d65898e3d31c24d72985e827bfd9c601c8bc65/cmake-3.31.10-py3-none-manylinux_2_31_armv7l.whl", hash = "sha256:91410816db3beefe2f6032d721f9978c98dc7646e9992c0325486597164fab81", size = 24986234, upload-time = "2025-11-20T17:07:21.596Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/634e46413472be742f3f422f159c41079bdc8ffba67538228f94a166c9ee/cmake-3.31.10-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:c2e5361dea9754ed3b06cf834894fb47dcbe7036d5e5d87acaeb10ff3dd5fd10", size = 27849273, upload-time = "2025-11-20T17:07:24.369Z" }, + { url = "https://files.pythonhosted.org/packages/6f/af/fac7ee4d79b688b94b4f6a6e5c4b080dca7594342576ad88a52b02a2d4eb/cmake-3.31.10-py3-none-musllinux_1_1_i686.whl", hash = "sha256:6970bb75c4dfc28cc31ff0cd848194d09094ae00d605181e1345b2ff70b61050", size = 31391299, upload-time = "2025-11-20T17:07:27.228Z" }, + { url = "https://files.pythonhosted.org/packages/d4/14/62339280a675106227ff650166c2899fe9f822ef9b855365563e71115125/cmake-3.31.10-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:4cefb0a28ac1268b4eed4b595bf3aaff8de9704089066027700ec36584eccab8", size = 32105563, upload-time = "2025-11-20T17:07:34.352Z" }, + { url = "https://files.pythonhosted.org/packages/ba/19/a3014beb02b344599e7a879f9c91d5e388aa76924b1369e13ffd535d613d/cmake-3.31.10-py3-none-musllinux_1_1_s390x.whl", hash = "sha256:b331984de38dbda22d676f8812c8905526341ba7b397fe8c359255ff4d051193", size = 27972718, upload-time = "2025-11-20T17:07:37.492Z" }, + { url = "https://files.pythonhosted.org/packages/b0/53/63b70d583c93352beeb692f0ec6bf4dede96f92df85c009577a663be304a/cmake-3.31.10-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:678fc23db37cc69f01e18eb28790450ecc9401fd2fcd43364cc18f92330c12c2", size = 29497491, upload-time = "2025-11-20T17:07:40.316Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a3/9d3a3881e70b947abe2d779e4c37d1aa9ac7f8339354e78d6036d520a220/cmake-3.31.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e135d5f1e59f1dc1c80eea87321977d6c0eff86cb601c28e0965a1dd457ea587", size = 33183971, upload-time = "2025-11-20T17:07:43.392Z" }, + { url = "https://files.pythonhosted.org/packages/06/f2/8e13be79373ef808659e52680643e0388057060e2627757b90df72c50681/cmake-3.31.10-py3-none-win32.whl", hash = "sha256:b059a1810a2ce766b3e531bdc8d730bc192e260a9fa7dec7a0eb7a053d6063c7", size = 33416497, upload-time = "2025-11-20T17:07:46.467Z" }, + { url = "https://files.pythonhosted.org/packages/84/4b/e433ab430c580ec8e3d54cb2ec5c7ea76ae0b1e6ef2c2998c854f21d7780/cmake-3.31.10-py3-none-win_amd64.whl", hash = "sha256:f1ea1fe826355560e8976c3d5794d9357444209bc0e0d56676c71e6a571fd474", size = 36630429, upload-time = "2025-11-20T17:07:49.445Z" }, + { url = "https://files.pythonhosted.org/packages/9f/c3/4eb3288ccd779556fee4b7b0955bdb14545bbae83f85f7c819dde8013708/cmake-3.31.10-py3-none-win_arm64.whl", hash = "sha256:422a54711aa977af19d59b8f6010354cdda0b72a2e6d702b6d892e3e2cdf98a2", size = 35457178, upload-time = "2025-11-20T17:07:52.367Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -682,6 +720,18 @@ nvtx = [ { name = "nvidia-nvtx", marker = "platform_machine == 'aarch64' or platform_machine == 'x86_64'" }, ] +[[package]] +name = "delvewheel" +version = "1.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pefile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/8d/ad1ecad995732a6c53086ce3bf20479d37a970acc80b7bdb4ab1eb156f2e/delvewheel-1.13.1.tar.gz", hash = "sha256:ae445f35f411c367f5b350431ac5f1435af8128bff31ccf34035a409704da8c6", size = 64796, upload-time = "2026-08-28T18:31:07.461Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/d0/fc48bf4c00b80c1ced5ce3740ea0c5d040758dafce385275e5de559375a4/delvewheel-1.13.1-py3-none-any.whl", hash = "sha256:1b3bc696193a57e322b8bfd644de240be6e003066aae44cc3d5aef8cbee22ca3", size = 60375, upload-time = "2026-08-28T18:31:06.18Z" }, +] + [[package]] name = "distlib" version = "0.4.3" @@ -1045,6 +1095,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d8/c6/32d68bfbf1d0c36888530ef6fd72864861af23dc546302b41033471a8c3a/llvmlite-0.49.0-cp314-cp314t-win_amd64.whl", hash = "sha256:be637e465010bc9c50f070468f7f1cf5385e92fee364d192dd5e6cea790ecba9", size = 42986602, upload-time = "2026-08-11T16:25:57.69Z" }, ] +[[package]] +name = "macholib" +version = "1.16.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "altgraph" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/2f/97589876ea967487978071c9042518d28b958d87b17dceb7cdc1d881f963/macholib-1.16.4.tar.gz", hash = "sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362", size = 59427, upload-time = "2025-11-22T08:28:38.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -1128,6 +1190,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, ] +[[package]] +name = "meson" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/48/91/d58a3eb45ed54bf32b96806dd2f4efd407f7a9675953e15e8ef257840a0d/meson-1.12.0.tar.gz", hash = "sha256:88afe0c20e52030218924ac37d0c81c59b4b5f3ae3752c8c6d7470c7d365886c", size = 2518280, upload-time = "2026-08-10T22:10:27.439Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/68/b0117422eb0a46d9d8d9e328f0c5b5c835179bfc058688bca35c90c89eba/meson-1.12.0-py3-none-any.whl", hash = "sha256:71f133147fa0fcfe8f4df49fa1045771064947834538409e5d97b3613aac8b4e", size = 1106208, upload-time = "2026-08-10T22:10:23.093Z" }, +] + +[[package]] +name = "meson-python" +version = "0.21.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "meson" }, + { name = "packaging" }, + { name = "pyproject-metadata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/f2/ab554fe4f020ec5f0ab4e4af04318e6ab99660f8d8d14e3d064db2b786a6/meson_python-0.21.1.tar.gz", hash = "sha256:78b3345dcbc0fed7b939e7e37a9faab35bddaae07bf62e7542c8ad479c395af5", size = 113878, upload-time = "2026-09-11T14:00:59.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/4f/03aeed5a32e7e8158d8c617fe65b622410db974fe02e3bd78da9689a44fd/meson_python-0.21.1-py3-none-any.whl", hash = "sha256:270bc9b78957c47e0aa1758ad616dba3f943d8f9cbdb944d318c3c1c7a49e4bd", size = 29579, upload-time = "2026-09-11T14:00:58.133Z" }, +] + [[package]] name = "more-itertools" version = "11.1.0" @@ -1224,6 +1309,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, ] +[[package]] +name = "ninja" +version = "1.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/73/79a0b22fc731989c708068427579e840a6cf4e937fe7ae5c5d0b7356ac22/ninja-1.13.0.tar.gz", hash = "sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978", size = 242558, upload-time = "2025-08-11T15:10:19.421Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/74/d02409ed2aa865e051b7edda22ad416a39d81a84980f544f8de717cab133/ninja-1.13.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1", size = 310125, upload-time = "2025-08-11T15:09:50.971Z" }, + { url = "https://files.pythonhosted.org/packages/8e/de/6e1cd6b84b412ac1ef327b76f0641aeb5dcc01e9d3f9eee0286d0c34fd93/ninja-1.13.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630", size = 177467, upload-time = "2025-08-11T15:09:52.767Z" }, + { url = "https://files.pythonhosted.org/packages/c8/83/49320fb6e58ae3c079381e333575fdbcf1cca3506ee160a2dcce775046fa/ninja-1.13.0-py3-none-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:be7f478ff9f96a128b599a964fc60a6a87b9fa332ee1bd44fa243ac88d50291c", size = 187834, upload-time = "2025-08-11T15:09:54.115Z" }, + { url = "https://files.pythonhosted.org/packages/56/c7/ba22748fb59f7f896b609cd3e568d28a0a367a6d953c24c461fe04fc4433/ninja-1.13.0-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:60056592cf495e9a6a4bea3cd178903056ecb0943e4de45a2ea825edb6dc8d3e", size = 202736, upload-time = "2025-08-11T15:09:55.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/22/d1de07632b78ac8e6b785f41fa9aad7a978ec8c0a1bf15772def36d77aac/ninja-1.13.0-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:1c97223cdda0417f414bf864cfb73b72d8777e57ebb279c5f6de368de0062988", size = 179034, upload-time = "2025-08-11T15:09:57.394Z" }, + { url = "https://files.pythonhosted.org/packages/ed/de/0e6edf44d6a04dabd0318a519125ed0415ce437ad5a1ec9b9be03d9048cf/ninja-1.13.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fb46acf6b93b8dd0322adc3a4945452a4e774b75b91293bafcc7b7f8e6517dfa", size = 180716, upload-time = "2025-08-11T15:09:58.696Z" }, + { url = "https://files.pythonhosted.org/packages/54/28/938b562f9057aaa4d6bfbeaa05e81899a47aebb3ba6751e36c027a7f5ff7/ninja-1.13.0-py3-none-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4be9c1b082d244b1ad7ef41eb8ab088aae8c109a9f3f0b3e56a252d3e00f42c1", size = 146843, upload-time = "2025-08-11T15:10:00.046Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fb/d06a3838de4f8ab866e44ee52a797b5491df823901c54943b2adb0389fbb/ninja-1.13.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6739d3352073341ad284246f81339a384eec091d9851a886dfa5b00a6d48b3e2", size = 154402, upload-time = "2025-08-11T15:10:01.657Z" }, + { url = "https://files.pythonhosted.org/packages/31/bf/0d7808af695ceddc763cf251b84a9892cd7f51622dc8b4c89d5012779f06/ninja-1.13.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11be2d22027bde06f14c343f01d31446747dbb51e72d00decca2eb99be911e2f", size = 552388, upload-time = "2025-08-11T15:10:03.349Z" }, + { url = "https://files.pythonhosted.org/packages/9d/70/c99d0c2c809f992752453cce312848abb3b1607e56d4cd1b6cded317351a/ninja-1.13.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:aa45b4037b313c2f698bc13306239b8b93b4680eb47e287773156ac9e9304714", size = 472501, upload-time = "2025-08-11T15:10:04.735Z" }, + { url = "https://files.pythonhosted.org/packages/9f/43/c217b1153f0e499652f5e0766da8523ce3480f0a951039c7af115e224d55/ninja-1.13.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f8e1e8a1a30835eeb51db05cf5a67151ad37542f5a4af2a438e9490915e5b72", size = 638280, upload-time = "2025-08-11T15:10:06.512Z" }, + { url = "https://files.pythonhosted.org/packages/8c/45/9151bba2c8d0ae2b6260f71696330590de5850e5574b7b5694dce6023e20/ninja-1.13.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:3d7d7779d12cb20c6d054c61b702139fd23a7a964ec8f2c823f1ab1b084150db", size = 642420, upload-time = "2025-08-11T15:10:08.35Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/95752eb635bb8ad27d101d71bef15bc63049de23f299e312878fc21cb2da/ninja-1.13.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:d741a5e6754e0bda767e3274a0f0deeef4807f1fec6c0d7921a0244018926ae5", size = 585106, upload-time = "2025-08-11T15:10:09.818Z" }, + { url = "https://files.pythonhosted.org/packages/c1/31/aa56a1a286703800c0cbe39fb4e82811c277772dc8cd084f442dd8e2938a/ninja-1.13.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:e8bad11f8a00b64137e9b315b137d8bb6cbf3086fbdc43bf1f90fd33324d2e96", size = 707138, upload-time = "2025-08-11T15:10:11.366Z" }, + { url = "https://files.pythonhosted.org/packages/34/6f/5f5a54a1041af945130abdb2b8529cbef0cdcbbf9bcf3f4195378319d29a/ninja-1.13.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b4f2a072db3c0f944c32793e91532d8948d20d9ab83da9c0c7c15b5768072200", size = 581758, upload-time = "2025-08-11T15:10:13.295Z" }, + { url = "https://files.pythonhosted.org/packages/95/97/51359c77527d45943fe7a94d00a3843b81162e6c4244b3579fe8fc54cb9c/ninja-1.13.0-py3-none-win32.whl", hash = "sha256:8cfbb80b4a53456ae8a39f90ae3d7a2129f45ea164f43fadfa15dc38c4aef1c9", size = 267201, upload-time = "2025-08-11T15:10:15.158Z" }, + { url = "https://files.pythonhosted.org/packages/29/45/c0adfbfb0b5895aa18cec400c535b4f7ff3e52536e0403602fc1a23f7de9/ninja-1.13.0-py3-none-win_amd64.whl", hash = "sha256:fb8ee8719f8af47fed145cced4a85f0755dd55d45b2bddaf7431fa89803c5f3e", size = 309975, upload-time = "2025-08-11T15:10:16.697Z" }, + { url = "https://files.pythonhosted.org/packages/df/93/a7b983643d1253bb223234b5b226e69de6cda02b76cdca7770f684b795f5/ninja-1.13.0-py3-none-win_arm64.whl", hash = "sha256:3c0b40b1f0bba764644385319028650087b4c1b18cdfa6f45cb39a3669b81aa9", size = 290806, upload-time = "2025-08-11T15:10:18.018Z" }, +] + [[package]] name = "nodeenv" version = "1.10.0" @@ -1272,7 +1383,8 @@ name = "numpy" version = "2.4.6" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.12'", + "python_full_version < '3.12' and sys_platform != 'ios'", + "python_full_version < '3.12' and sys_platform == 'ios'", ] sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } wheels = [ @@ -1354,8 +1466,10 @@ name = "numpy" version = "2.5.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.15'", - "python_full_version >= '3.12' and python_full_version < '3.15'", + "python_full_version >= '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.15' and sys_platform == 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform == 'ios'", ] sdist = { url = "https://files.pythonhosted.org/packages/9a/80/db0b4559e57ec36362bedbb05530a87fafbcb6067708c946967a41d449e7/numpy-2.5.2.tar.gz", hash = "sha256:d482d171c406ae88c5b19cad3b6a1c4c5209f886ab74bc44c2c865c23f52d860", size = 20773161, upload-time = "2026-08-09T13:48:27.962Z" } wheels = [ @@ -1650,6 +1764,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, ] +[[package]] +name = "pefile" +version = "2024.8.26" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, +] + +[[package]] +name = "pip" +version = "26.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/15/4500e320e6b101ec3b719ae85b697d9940b6cda672bc555bd6016fc60c6f/pip-26.2.1.tar.gz", hash = "sha256:f6ad667e89a1fe78046c8f13232b247200f5258d7828f3f7883d660878e0813f", size = 1848877, upload-time = "2026-08-04T22:51:14.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/6e/1736e5b4ae2b778ef2f81c47d797de9f891d4d8acb047a24ca37a60294dd/pip-26.2.1-py3-none-any.whl", hash = "sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e", size = 1816632, upload-time = "2026-08-04T22:51:12.472Z" }, +] + [[package]] name = "platformdirs" version = "4.11.3" @@ -1765,6 +1897,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, ] +[[package]] +name = "pyelftools" +version = "0.33" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/11/767522582afab1b884d277de0e6e011640cb9d7292a38694b4b1a1df1ae8/pyelftools-0.33.tar.gz", hash = "sha256:660d82dcbeb8e83d1702bd97f223f761625da06111c0cc988eac6b8ab0c1b61f", size = 15068655, upload-time = "2026-05-29T12:56:22.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2a/f9697576603dae937727827505a6126a066affb227034e77e6f9068910da/pyelftools-0.33-py3-none-any.whl", hash = "sha256:f215ad5f47d3f1373a21496a6c9e0707c622840d0622f23ff7ce08678b020036", size = 201178, upload-time = "2026-05-29T12:56:20.587Z" }, +] + [[package]] name = "pyflakes" version = "3.4.0" @@ -1906,6 +2047,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/eb/5fb627c2457046883c6fd12d25c44db40c12bcde4622dc0f30851108e106/pyobjc_framework_quartz-12.2.2-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:8f58c589b5a76ba98f186b1f3b19fb1c8b730e82351f81fb62e6194f64a71622", size = 224767, upload-time = "2026-08-11T19:40:30.991Z" }, ] +[[package]] +name = "pyproject-metadata" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/76/1cae539918a7b1746d624c2f01560b793c22cd8c081157505bb9bbf0e34d/pyproject_metadata-0.12.1.tar.gz", hash = "sha256:8809a4df6fe08279b39a8890669506ed3158e0617855ac9aff098fcbe772ae4c", size = 48457, upload-time = "2026-07-04T02:19:32.029Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/8e/d883718e872abc214ba053f60f7e6edc2abd5ffbd1544beb01a9c92ddd3c/pyproject_metadata-0.12.1-py3-none-any.whl", hash = "sha256:f7162d580a96386a8eb096da06215f981f547d1490f03055ef99e323bc2da427", size = 23452, upload-time = "2026-07-04T02:19:30.657Z" }, +] + [[package]] name = "pytest" version = "9.1.1" @@ -2227,6 +2380,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6f/b6/26e41975febae63b7a6e3e02f32cff6cff2e4f10d19c929082f56aebf7c6/regex-2026.7.19-cp314-cp314t-win_arm64.whl", hash = "sha256:9a15e785f244f3e07847b984ce8773fc3da10a9f3c131cc49a4c5b4d672b4547", size = 283451, upload-time = "2026-07-19T00:19:46.639Z" }, ] +[[package]] +name = "repairwheel" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "delvewheel" }, + { name = "macholib" }, + { name = "packaging" }, + { name = "pefile" }, + { name = "pyelftools" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/74/e4c2ed3d34cde8cf790f4f5d99fb7b06933864ca8b5b6eed1dd237c7b763/repairwheel-0.7.0.tar.gz", hash = "sha256:46083dad76e35595712ae593c1c9f112fb3f37a0e63268906e6de8182de55122", size = 286421, upload-time = "2026-08-29T04:07:10.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/12/bbc4f17fa2661e40342a1e36ad099f085bb83d6dbd025fb00c69e313182f/repairwheel-0.7.0-py3-none-any.whl", hash = "sha256:7fff43ed5abbf9710ef5ea6478c10cfd551aae043f445fd46307d4b602674ce0", size = 146908, upload-time = "2026-08-29T04:07:11.442Z" }, +] + [[package]] name = "requests" version = "2.34.2" @@ -2253,11 +2423,25 @@ wheels = [ [[package]] name = "setuptools" -version = "84.0.0" +version = "81.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/44/f5da03a8ef95d369145c5bb53050e7877c9f3d312e128605fd9504829143/setuptools-84.0.0.tar.gz", hash = "sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73", size = 1168449, upload-time = "2026-08-08T18:27:58.365Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl", hash = "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", size = 818216, upload-time = "2026-08-08T18:27:56.719Z" }, + { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" }, +] + +[[package]] +name = "setuptools-scm" +version = "10.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "setuptools" }, + { name = "vcs-versioning" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/87/1ff7adcf6e03021ae58ce401565be3c9b8c739a44d14a8253d38b3754117/setuptools_scm-10.2.3.tar.gz", hash = "sha256:f179ed3e2a63cf5823e5ee9aa9ca08386219400443a0553224d72dde3f206b44", size = 67696, upload-time = "2026-09-03T13:03:29.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/00/e9c0591b77186f6c1a8479500456ee72cd30730836c58b7a8a2654909c23/setuptools_scm-10.2.3-py3-none-any.whl", hash = "sha256:7fcf8ff55c95eb8b572a23c81495e5559b9b90f3e82fcf0952bb76c37de27a81", size = 29123, upload-time = "2026-09-03T13:03:28.346Z" }, ] [[package]] @@ -2331,7 +2515,8 @@ name = "sphinx" version = "9.0.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.12'", + "python_full_version < '3.12' and sys_platform != 'ios'", + "python_full_version < '3.12' and sys_platform == 'ios'", ] dependencies = [ { name = "alabaster" }, @@ -2362,8 +2547,10 @@ name = "sphinx" version = "9.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.15'", - "python_full_version >= '3.12' and python_full_version < '3.15'", + "python_full_version >= '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.15' and sys_platform == 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform != 'ios'", + "python_full_version >= '3.12' and python_full_version < '3.15' and sys_platform == 'ios'", ] dependencies = [ { name = "alabaster" }, @@ -2752,6 +2939,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] +[[package]] +name = "vcs-versioning" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3e/97/792a4ef20344f9af3e16098b58b45eb5d6202259b84fc80c43bc000a5e6c/vcs_versioning-2.4.1.tar.gz", hash = "sha256:d4575de3115ec9434393c87c80ffb0eb98a16056bfe2b11ce0f3a97aff67fe0a", size = 164222, upload-time = "2026-09-16T07:47:40.267Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/20/29378edc8d7d2ce41892adc1356f4c6c6ae03b945d04ca6ade61afa3d5dc/vcs_versioning-2.4.1-py3-none-any.whl", hash = "sha256:b7089ec9bef67b2cad82148366e8eac4d63173f440ec62628282b59eb96bbcb0", size = 122157, upload-time = "2026-09-16T07:47:38.811Z" }, +] + [[package]] name = "virtualenv" version = "21.7.4" @@ -2815,6 +3014,16 @@ whisper = [ ] [package.dev-dependencies] +installer-build = [ + { name = "cmake" }, + { name = "meson-python" }, + { name = "ninja" }, + { name = "pip" }, + { name = "repairwheel" }, + { name = "setuptools" }, + { name = "setuptools-scm" }, + { name = "wheel" }, +] lint = [ { name = "black" }, { name = "flake8" }, @@ -2850,6 +3059,16 @@ requires-dist = [ provides-extras = ["vosk", "whisper", "parakeet", "faster-whisper", "vad", "dev", "docs"] [package.metadata.requires-dev] +installer-build = [ + { name = "cmake", specifier = "==3.31.10" }, + { name = "meson-python", specifier = ">=0.16" }, + { name = "ninja", specifier = "==1.13.0" }, + { name = "pip", specifier = ">=25.3,<27" }, + { name = "repairwheel" }, + { name = "setuptools", specifier = ">=77,<82" }, + { name = "setuptools-scm", specifier = ">=8" }, + { name = "wheel" }, +] lint = [ { name = "black", specifier = ">=23.0.0" }, { name = "flake8", specifier = ">=6.0.0" }, @@ -2988,3 +3207,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bf/e3/91e297e41381d9131f3142a9c1a50389fd96b98125ce9b81526fa4e14b9f/websockets-17.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:afbce6e3f0fac32dc87c2a0d84869d1a706460d64f39f3889386413e6e4d3d26", size = 213434, upload-time = "2026-07-31T11:31:24.707Z" }, { url = "https://files.pythonhosted.org/packages/09/ce/3929538b2b9918f5eee623fbf3346893973191f6df93f19bbda097bd7bb7/websockets-17.0.1-py3-none-any.whl", hash = "sha256:c6be9cba65c65cc76dfa3d4619e359ff02a4476c74e179b215236c11a0b32345", size = 206718, upload-time = "2026-07-31T11:31:26.037Z" }, ] + +[[package]] +name = "wheel" +version = "0.48.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/20/50ed6bdf27dec98b568a8ae25dc599f35baa3d9709f9e83fd1edb56b9a90/wheel-0.48.0.tar.gz", hash = "sha256:94800765601e9171bf5d58d066e640662842bcedcbab982b2c90787a2c987322", size = 66471, upload-time = "2026-08-11T22:02:27.327Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/29/69cfbb602cd91690c55d38ba9fe53e6a7e76a6fa647bf38f19c138d25449/wheel-0.48.0-py3-none-any.whl", hash = "sha256:3217dcc807155e45db462d7ef2431f5ddda0d7273b700d05a67b271ceb1287ab", size = 33320, upload-time = "2026-08-11T22:02:26.1Z" }, +]