product: assert audience: test-developer authority: normative
Python Dependencies and Offline Environments
Production test stations are frequently deployed in air-gapped networks with no internet access. The Python runner Docker image ships with only the gRPC transport libraries — nothing else. Third-party packages MUST be made available before a test executes.
How pipPackages works
Declare dependencies in package.json:
{
"requirements": {
"minPythonVersion": "3.11",
"pipPackages": ["requests>=2.32.0"]
}
}
The Python runner automatically installs these packages at startup by scanning every
installed package and reading pipPackages from each package.json.
These are tried in order — they are a fallback chain, not alternatives:
| Order | Condition | Action |
|---|---|---|
| 1 | Package has wheels/ with .whl files |
pip install --no-index --find-links wheels/ (offline) |
| 2 | Step 1 failed or there is no wheels/, and AllowOnlinePip is true (dev only) |
pip install from PyPI |
| 3 | Neither | Warning logged; test fails with a pip dependencies … could not be installed error |
Vendoring wheels for production
Step 1 — Download wheels on a machine with internet access:
# Helper script (reads pipPackages from package.json)
.\scripts\vendor-wheels.ps1 -PackagePath "path\to\my-package"
# Or manually
pip download requests>=2.32.0 \
--dest wheels/ \
--platform manylinux2014_x86_64 \
--python-version 3.13 \
--only-binary=:all:
The Python runner runs on
python:3.13-slim(Debian Linux, x86_64). Always download wheels formanylinux2014_x86_64and Python 3.13.This matters for compiled wheels. pip silently ignores a wheel whose ABI tag (
cp311,cp313, …) does not match the interpreter, then reportsERROR: Could not find a version that satisfies the requirement <pkg> (from versions: none)— which reads like the wheel was never vendored. Pure-Python wheels (py3-none-any) are unaffected, so a mismatch typically singles out one compiled package (numpy, matplotlib, pillow, cffi …). The runner detects this case and says so explicitly in the step error; re-vendor with the matching--python-version. Reinstalling the package will NOT fix it.
runner_type: python3.11in test YAML is an unrelated routing token — it selects the Python runner, it does not pin an interpreter version.
Step 2 — Commit wheels into wheels/ in your package. The runner installs them
automatically at startup — no manual docker exec required.
How the runner finds Python modules
The runner adds to sys.path at startup:
/app/scripts— legacy mount for ad-hoc scripts.<package>/python_modules/for every installed package — picked up automatically on every step invocation.
Development vs production
- Development: Set the station config key
AllowOnlinePip=trueto install from PyPI. This is a station config key, not an environment variable — the runner reads it when the first step executes, so a station can be switched online without a restart. - Production: MUST vendor wheels. MUST NOT rely on internet access.