Dependency Contract¶
The six root requirements inputs and the two packaged Xpra inputs own every exact
direct Python dependency.
Each is paired with a same-stem requirements*.txt lock generated by
pip-compile with hashes; locks must never be edited manually. Every tool input
includes requirements.in exactly once, so all
runtime-derived environments resolve the same published runtime pin.
| Audience | Direct input | Generated lock | Purpose |
|---|---|---|---|
| runtime | requirements.in |
requirements.txt |
published ssh-wrapper runtime |
| quality | requirements-quality.in |
requirements-quality.txt |
Ruff, mypy, Bandit, audit, licenses |
| test | requirements-test.in |
requirements-test.txt |
pytest and coverage |
| package | requirements-package.in |
requirements-package.txt |
wheel/sdist construction |
| standalone | requirements-standalone.in |
requirements-standalone.txt |
native PyInstaller build |
| docs | requirements-docs.in |
requirements-docs.txt |
strict MkDocs rendering |
| Xpra client | requirements-xpra.in |
requirements-xpra.txt |
isolated matching PyOpenGL additions |
| Xpra builder | requirements-xpra-build.in |
requirements-xpra-build.txt |
temporary accelerator source-build tools |
pyproject.toml declares runtime dependencies as
dynamic setuptools metadata read from requirements.in. It contains no
second copy of those versions and no internal quality, test, package,
standalone, or documentation extras. Its build-system setuptools range
expresses a backend capability; the exact setuptools used by project commands
is pinned in requirements-package.in.
ssh-wrapper is the sole runtime dependency; its version is maintained only in
requirements.in. The standard-library helper
tools/runtime_dependency.py reads the
current input for all six Make environments, clean-install and standalone smoke,
and live dependency identity checks. Make verifies it both before reusing an
environment and after installing one, so a stale lock cannot produce a successful
preparation with a different runtime version. The lock validator compares the generated
graphs against the same input. Tests change a fixture input to prove that a new
pin needs no copied version constants or documentation edits.
Every audience that needs it resolves the reviewed PyPI wheel through generated hashes. This repository
does not vendor it, build it from another checkout, or add an import path to an
uninstalled source tree.
The Xpra input is independent of the Elsewindow runtime. Its PyOpenGL pair must
stay on the same upstream version and is packaged with wheel, sdist and native
executables. make runtime-venv prepares this separate environment as well;
--prepare-xpra provides the installed and standalone setup route. Dependabot
includes both the repository root and elsewindow/ manifest directories.
The separate build lock supplies Cython, NumPy headers, and setuptools during
preparation only; these packages are removed from the prepared Xpra venv.
When an accelerator wheel is unavailable, notably on Linux arm64, its verified
source archive is built without unpinned build-isolation downloads. The host
must provide a C compiler and system Python headers for that route.
Run make lock only after an intentional direct dependency change in a
requirements*.in file and
make refresh-dependencies for a reviewed whole-graph upgrade. Both use the
online resolver container. Never edit a lock manually. Environment targets
install with --require-hashes, binary-only policy, and pip check. The sole
source-build exception is the Xpra accelerator under the separate locked builder.
make freeze-check is an explicit online gate that recompiles every audience
against its current constraints.
make lock-validate checks exact ownership, pins, hashes, and wrapper
provenance. make dependency-snapshot produces all eight GitHub dependency
manifests deterministically.
Dependabot treats every .in file as a native pip-compile manifest, updates
its matching .txt lock, and groups all ordinary Python changes into one pull
request. pyproject.toml is excluded from its pip manifests so a plain
requirements updater cannot take ownership of generated locks. The
coordinated ssh-wrapper runtime contract remains excluded from automatic
version changes. Both local resolver stages pin the pip==26.1.1 and
pip-tools==7.5.3 pair used by Dependabot when this contract was established;
a future resolver migration must update both stages together and reproduce all
eight locks. GitHub Actions updates remain grouped into one other pull request,
so one scheduled run opens at most one update per ecosystem.
make audit checks every lock and accepts only exact findings in
dependency-audit-exceptions.json;
an unused exception fails as stale. make licenses inventories the complete
standalone build environment, a conservative superset of bundled Python
packages; make outdated is an explicit online review aid. Maintainer locks
are not a public installation interface: users install the published
distribution normally.