wibench-venv: virtual environment manager
Watermarking algorithms, attacks, datasets and metrics often pin conflicting package versions, so a single virtual environment cannot host all of them. wibench-venv solves this by grouping requirement files into as few mutually compatible sets as possible and building one venv per group. At run time wibench inspects the pipeline config and transparently re-executes itself with the python of a venv that covers every requirement of the config.
File layout
Everything lives under profiles/:
profiles/
├── common/ # NOT a profile, shared by all profiles
│ ├── base/
│ │ └── wibench.txt # mandatory: included in every group of every profile
│ └── common.txt # optional: participates in every profile's composition
├── image/ # a profile
│ ├── .python-version # (optional) Python version for all venvs of this profile
│ ├── requirements/
│ │ ├── common/ # same idea one level down, shared inside this profile only
│ │ │ ├── base/
│ │ │ │ └── base.txt # mandatory: included in every group of this profile
│ │ │ └── common.txt # optional: participates in this profile's composition
│ │ ├── algorithms/ # one txt per entity, e.g. trustmark.txt
│ │ ├── attacks/
│ │ ├── datasets/
│ │ └── metrics/
│ └── venvs/ # generated by wibench-venv
│ ├── venv0.txt # group: list of requirement files covered by venv0
│ ├── venv0.lock # fully pinned lock compiled from the group
│ └── venv0/ # the virtual environment itself
├── audio/
│ ├── .python-version
│ ├── requirements/
│ └── venvs/
└── your_profile/
└── ...
Requirement file roles:
profiles/common/base/*.txt— the mandatory base. Every group of every profile starts with these files; a requirement that conflicts with the base cannot be installed at all.profiles/common/*.txt— shared optional requirements. They join the composition of every profile like ordinary files: placed into groups where they fit, skipped where they conflict.profiles/<profile>/requirements/common/base/*.txt— the profile’s mandatory base. Same as the shared base, but scoped to one profile: every group of this profile starts with these files, other profiles ignore them completely. This is where the profile’s runtime stack lives (e.g.torchforimage) instead ofpyproject.toml, so anaudiovenv is not forced to carry it.profiles/<profile>/requirements/common/*.txt— optional requirements shared inside the profile. They participate only in this profile’s composition, like ordinary files.profiles/<profile>/requirements/**/*.txt— profile-specific requirements. The<entity_type>/<entity>.txtnaming (e.g.algorithms/trustmark.txt) is what connects a config entry to its requirement file.
Commands
(.venv) wibench-venv [STAGES]... [-p PROFILE] [-j JOBS] [-v]
Stage |
What it does |
|---|---|
|
Checks that each requirement file resolves together with the base; invalid files are excluded from the subsequent stages of this run (with a warning) |
|
Builds groups from scratch: computes the pairwise conflict graph, then greedily packs every compatible file into every group; writes |
|
Updates existing groups instead of rebuilding: keeps current members, packs new files into every group where they fit, creates new groups only for files that fit nowhere |
|
Compiles each |
|
Creates/recreates |
|
Shortcut for |
|
Shortcut for |
Running without arguments executes install only. Stages can be combined:
(.venv) wibench-venv rebuild # rebuild the default profile from scratch
(.venv) wibench-venv update -p audio # refresh audio venvs after adding a requirement
(.venv) wibench-venv compose lock # regroup and lock, don't install
compose and extend (and therefore rebuild and update) are mutually exclusive: use compose for a clean rebuild and extend to update existing groups in place (e.g. after adding a new requirement file). extend never removes a file from a group unless it no longer resolves or its requirement file was deleted, so group membership stays stable across runs.
Options:
-p, --profile— profile to operate on. Priority: this option >WIBENCH_PROFILEenvironment variable > default (image). The namecommonis rejected since it is not a profile.-j, --jobs— maximum number of concurrentuvprocesses (default 8). Compatibility checks and locking run concurrently; results are cached, so repeated checks of the same file combination cost nothing.-v, --verbose— escalate logging, same scheme as the main CLI:-vextended tracebacks (backtrace),-vvadds variable diagnostics (diagnose),-vvvand beyond lower the log level one step per extrav(-vvv= DEBUG). Failed resolutions duringcompose/extendare logged at DEBUG (conflicts there are expected and numerous), so use-vvvto see why two files don’t fit into one venv; failures on the other stages are visible without it.
Per‑profile Python version
Put the desired version into profiles/<profile>/.python-version (a single line, e.g. 3.11). It is passed to every uv pip compile and uv venv call, so both resolution and the built venvs use that version. Without the file, uv picks the interpreter as usual (including the repository-level .python-version). After changing the version, rerun wibench-venv rebuild -p <profile> — resolution results may differ.
How the pipeline picks a venv
When you run wibench --config ..., it collects the requirements of every entity in the config and looks for a group (venvN.txt) that covers all of them:
with an explicit profile (
wibench --profileorWIBENCH_PROFILE), only that profile is searched;otherwise all profiles are searched, the default one first.
If the current interpreter is not from a matching venv, wibench re-executes itself with the matched venv’s python and pins the profile via WIBENCH_PROFILE for its worker subprocesses. If no group covers the config, the error lists what is missing per group — remove those entries from the config or rebuild the venvs.
Practical notes
Determinism. Group composition is deterministic: files are ordered by conflict degree with ties broken by path, so the same inputs always produce the same groups.
Pin git dependencies to a commit. Unpinned refs like
git+https://github.com/foo/barforce a network round-trip on every resolution and are the main source of rate-limit errors and slowdowns; pin them (...@<sha>) souvcan resolve from its cache.Transient network errors (HTTP 429, git fetch failures) are retried with exponential backoff. During
validatea file that keeps failing is marked invalid with a warning — check the log before trusting a rebuild made on a flaky network, otherwise the file silently drops out of the groups.Stale artifacts. When a rebuild produces fewer groups than before, the leftover
venvN.txt,venvN.lockandvenvN/are deleted automatically.