Skip to content

environment

The environment of a run: a lock from the model and its snapshotted libraries.

The image of a run holds only the third party dependencies. The code of the model repository and of the libraries comes from snapshots which the pod mounts read-only and installs editable at start (SIMRUN_EDITABLE, see simrun.worker), so a change of the code never rebuilds an image and a change of a dependency does.

A pod installs the snapshots without build isolation and without an index, so the image holds their build backends: the [build-system].requires of the model and of every library (the legacy backend of setuptools without a [build-system], PEP 517) and what the backend asks for an editable build (get_requires_for_build_editable, PEP 660, e.g. editables of hatchling), which a hook asks at resolve time in an environment of uv run with the static requirements, in a shadow tree of the snapshot. They are dependencies of the temporary project, so the lock pins them with the third party dependencies and the image installs them. Their versions are the pins of a constraints file of the service (build_constraints.txt, BUILD_CONSTRAINTS), for the packages the uv.lock of the model does not have, so a release of a backend changes no lock.

The lock is resolved in a temporary project, a writable shadow tree of the model (simrun.worker.shadow_tree: its directories, links to its files) with its pyproject.toml changed and a copy of its uv.lock, and a directory .simrun-store with a shadow tree of every library at .simrun-store/<snapshot>. uv lock builds the metadata of a source with dynamic metadata, which a backend writes next to the sources (e.g. the *.egg-info of setuptools): into the shadows, never into the snapshots, which are named by the hash of their content. The sources of the libraries are the relative paths .simrun-store/<snapshot>, so the lock carries these paths and not the place the store is mounted at (/mnt/cluster on the development server, /store in the service): the same snapshots give the same lock and hash anywhere.

Environment dataclass

Environment(
    lock,
    lock_sha256,
    python,
    simrun_version,
    editable,
    requirements="",
    build_requirements=(),
)

The resolved environment of a run.

Attributes:

Name Type Description
lock str

Text of the uv.lock.

lock_sha256 str

Hash of the lock and the python version, the identity of the image.

python str

Python version of the image.

simrun_version str

Version of the simrun wheel the image installs, with the hash of the wheel when the service has one.

editable list[str]

Snapshot directories of the model and the libraries, relative to the store in the order of the sources, installed at pod start.

requirements str

The third party dependencies of the lock as pinned requirements, without the model and the snapshotted libraries.

build_requirements tuple[str, ...]

The requirements of the build backends of the sources, which the lock pins with the dependencies.

normalise

normalise(name)

Normalised name of a package (PEP 503), as uv.lock writes it.

load_constraints

load_constraints(path)

The pins of a constraints file by normalised name, e.g. hatchling==1.33.0.

Raises:

Type Description
ValueError

A line is no exact pin <name>==<version>.

build_requirements

build_requirements(directory, name, python, pins=None)

What building a source editable needs: its build system and its backend's hook.

Parameters:

Name Type Description Default
directory Path

The snapshot of the source, with its pyproject.toml.

required
name str

The name of the source, for messages.

required
python str

The python version the hook runs with.

required
pins dict[str, str] | None

The pinned versions of build backends (load_constraints), applied to the environment the hook runs in.

None

Returns:

Type Description
list[str]

[build-system].requires and the result of the backend's

list[str]

get_requires_for_build_editable.

Raises:

Type Description
RuntimeError

The backend cannot be loaded or its hook fails.

resolve_environment

resolve_environment(
    store,
    model,
    libraries,
    python="3.14",
    *,
    simrun_version,
    build_constraints=BUILD_CONSTRAINTS,
)

Lock the dependencies of the model with its libraries as snapshot paths.

Parameters:

Name Type Description Default
store Path

Root of the run store.

required
model SourceProvenance

Snapshot of the model repository, which has the pyproject.toml.

required
libraries list[SourceProvenance]

Snapshots of the libraries; each replaces the entry of [tool.uv.sources] of its package name, the other entries are kept.

required
python str

Python version of the image.

'3.14'
simrun_version str

Version of the simrun wheel of the image, part of the hash (the service adds the hash of the wheel, Submitter._harness).

required
build_constraints Path

The pinned versions of the build backends; a pin of a package the uv.lock of the model does not have constrains the lock.

BUILD_CONSTRAINTS

Returns:

Type Description
Environment

The environment.

Raises:

Type Description
ValueError

A snapshot has no pyproject.toml, the model has no uv.lock (it would resolve against the live index and the hash would drift), or the model depends on a local package which is not a snapshotted source.

RuntimeError

uv fails to lock, or a build backend cannot tell what an editable build needs.

image_ref

image_ref(env, registry, dockerfile_text)

Reference of the image of an environment in the registry.

Parameters:

Name Type Description Default
env Environment

The environment.

required
registry str

The registry of the cluster.

required
dockerfile_text str

The Dockerfile of the image (dockerfile); with the lock it is the identity of the image, so another base image or other system packages give another image instead of the one built before.

required

dockerfile

dockerfile(env, base_image, wheel, system_packages=())

Dockerfile of the image: the dependencies, build backends and simrun, no source.

The packages are installed with their bytecode compiled, so a pod does not compile the modules it imports, and with the downloads of uv in a cache of BuildKit (UV_CACHE), so a build after a change of a dependency downloads only what changed. simrun is the last layer: a new harness rebuilds only it.

The pinned requirements are written with a heredoc, so no source is copied from the build context. The model and the libraries are installed at pod start.

Parameters:

Name Type Description Default
env Environment

The environment.

required
base_image str

The base image, with uv and the python of the environment, in the registry of the cluster (ClusterConfig.base_image_ref).

required
wheel str

File name of the simrun wheel in the build context, the only file copied; the harness of the service, never installed by name.

required
system_packages Sequence[str]

Debian packages installed before the requirements, the shared libraries their wheels link (ClusterConfig.system_packages); git as well when a requirement is locked from a git repository.

()