sp_validation.container¶
Manage this user’s local copy of the sp_validation container image.
Everyone runs their own image: the canonical paths are under your own cache, you refresh them when you want to, and nobody else’s refresh moves the ground under a running job.
There are two layers, and you only need the second when you want it:
the SIF (
~/.cache/sp_validation/sp_validation.sif) – a pristine, read-only copy of the published image. This is the default and the normal case.an optional sandbox (
~/.cache/sp_validation/sandbox/) – the same image unpacked into a writable directory, sopip installinside it sticks. This is the escape hatch for exploratory work that needs a package the image does not carry yet, and it is opt-in: nothing builds one for you.
Subcommands, exposed as the spv-container console script:
spv-container pull # fetch the tag to the canonical path
spv-container status # what is here, and how current is it
spv-container sandbox # unpack the SIF into a writable dir
spv-container exec <cmd...> # run something inside it
spv-container exec --writable <cmd...> # ... with writes that persist
Everything resolves the same image in the same order – sandbox if it exists, else the SIF, else the registry tag – and that includes the Snakemake workflow, so a package you installed into your sandbox is there for your workflow jobs too.
This module is deliberately stdlib-only (argparse/subprocess/
pathlib). It runs on the host, outside the container, where the science
stack is not installed – so it must import without it. That also means it works
straight from a checkout with no install at all:
python3 src/sp_validation/container.py pull
- resolve_image()[source]¶
Return
(path_or_uri, kind)for the image everything should run.The one resolution order, shared by the CLI and the workflow: the writable sandbox if it exists, else the pristine SIF if it exists, else the registry tag for Snakemake to pull.
kindis"sandbox","sif"or"tag".
- image_labels(sif)[source]¶
Return the image’s OCI labels as a dict, or
{}if unreadable.Never raises: a missing file, a missing
apptainer, or a corrupt image all mean “we don’t know”, which every caller here treats as non-fatal.