Skip to navigation

nemo_gym.sandbox.compose_volumes

View as Markdown

Plan the volumes of a Compose document for a sandbox that has no Docker volumes.

Parses each service’s volume entries in their short and long forms, checks the target path and the bind source against the task folder, refuses options the sandbox cannot honour, resolves links before anything is read, and returns the plan the adapter uploads and mounts: bind mounts as uploads, named volumes as shared storage, the logs tree kept apart. Every symbol is M22 and the module reads only the standard library.

Module Contents

Classes

NameDescription
ComposeVolumeErrorA Compose volumes entry prepare cannot run; name is the volume, source or field it names.

Functions

NameDescription
_bind_sourceA bind source as a host path: relative to base_dir (the Compose file’s folder), ~ expanded.
_checked_targetA mount target the group can serve: an absolute container path below / with no .. segment.
absolute_linkThe first component of path below root that is a link with an absolute target, or None.
first_linkThe first symbolic link anywhere under folder (files or folders), or None.
lexical_targetA mount target in its lexical form: trailing and repeated separators and . segments dropped, so
parse_volumeOne volumes entry as a long-syntax mapping: type, source, target, read_only

Data

LOGS_TREE

_VOLUME_NOOP_OPTIONS

_VOLUME_OPTIONS

API

class nemo_gym.sandbox.compose_volumes.ComposeVolumeError(
name: str,
message: str
)

Bases: ValueError

A Compose volumes entry prepare cannot run; name is the volume, source or field it names.

nemo_gym.sandbox.compose_volumes._bind_source(
source: str,
base_dir: pathlib.Path,
where: str
) -> pathlib.Path

A bind source as a host path: relative to base_dir (the Compose file’s folder), ~ expanded.

~user for a user the host does not know cannot be resolved; it raises ComposeVolumeError naming the source, like any other bind source the task does not contain.

nemo_gym.sandbox.compose_volumes._checked_target(
target: typing.Any,
where: str
) -> str

A mount target the group can serve: an absolute container path below / with no .. segment.

The same rule for both syntaxes, and the one the Compose adapter applies to uploads, so a target it would refuse fails at prepare naming the field (target).

nemo_gym.sandbox.compose_volumes.absolute_link(
path: pathlib.Path,
root: pathlib.Path
) -> pathlib.Path | None

The first component of path below root that is a link with an absolute target, or None.

The server plans a task on a copy of its folder (links copied as links), where an absolute target still points into the original folder: a bind source reached through one resolves inside the task at prepare and outside the copy at seed. The planner refuses it, as the hub refuses such a link in a fetched task (_validate_task_tree), so the two agree. A relative link that stays inside the task is fine at both.

nemo_gym.sandbox.compose_volumes.first_link(
folder: pathlib.Path
) -> pathlib.Path | None

The first symbolic link anywhere under folder (files or folders), or None.

A folder a Compose file binds is uploaded entry by entry (a copy, not a mount); a link inside it would be read through, reaching whatever it points at on the host, so the planner and the Compose adapter both refuse one.

nemo_gym.sandbox.compose_volumes.lexical_target(
target: str
) -> str

A mount target in its lexical form: trailing and repeated separators and . segments dropped, so /app/output/, /app/output/. and //app/./output are all /app/output.

A target is recorded as written (/data/. stays /data/. in the planned document) and compared in this form, by the planner’s rule for a main logs bind and by the Compose adapter’s, which also names the link in it: a target that nests its source only once spelled out (/logs/verifier:/logs/.) is refused at prepare like /logs/verifier:/logs, and never linked over the tree it names (M22 review).

nemo_gym.sandbox.compose_volumes.parse_volume(
entry: typing.Any,
service: str
) -> dict[str, typing.Any]

One volumes entry as a long-syntax mapping: type, source, target, read_only and, for a named volume, volume.nocopy.

Short syntax SOURCE:TARGET[:OPTIONS] is parsed the way Compose does: a source starting with ., / or ~ is a bind mount, anything else a named volume. A bare TARGET (an anonymous volume), a tmpfs/npipe/cluster type, a bind propagation or an unknown option raises ComposeVolumeError naming the field: nothing in a sandbox group stands in for it.

nemo_gym.sandbox.compose_volumes.LOGS_TREE = '/logs'
nemo_gym.sandbox.compose_volumes._VOLUME_NOOP_OPTIONS = frozenset({'z', 'Z', 'cached', 'delegated', 'consistent'})
nemo_gym.sandbox.compose_volumes._VOLUME_OPTIONS = {'ro': {'read_only': True}, 'rw': {'read_only': False}, 'nocopy': {'nocopy': Tru...