utils.env package

Subpackages

Submodules

utils.env.builder module

Compose the .env value-set from static defaults plus runtime context.

Thin orchestrator: each variable’s mapping/computation lives in its own module under utils.env.handlers. build_env walks the ORDERED_HANDLERS registry, letting each handler read/write through an EnvBuilder.

class utils.env.builder.BuildContext(static: dict[str, str], static_comments: dict[str, str], repo_root: Path, on_gha: bool, on_act: bool)

Bases: object

Per-build inputs passed to every handler.

Attributes are read-only; per-handler scratch state lives on the EnvBuilder instead.

on_act: bool
on_gha: bool
repo_root: Path
static: dict[str, str]
static_comments: dict[str, str]
class utils.env.builder.EnvBuilder

Bases: object

Mirror bash : "${KEY:=value}" semantics with per-key comments.

setdefault falls back to the supplied value only when the process env has no non-empty value for the key. set is unconditional. get reads from the builder, falling back to the process env so derived values (e.g. INFINITO_CONTAINER) can be composed off previously-set keys.

comments: dict[str, str]
get(key: str) → str
set(key: str, value: str, *, comment: str = '') → str
setdefault(key: str, value: str, *, comment: str = '') → str
values: dict[str, str]
utils.env.builder.apply_custom_env(eb: EnvBuilder, repo_root: Path) → None

Overwrite every key found in <repo_root>/custom.env.

custom.env is the operator’s untracked override file; its values win over static defaults AND handler-computed values.

utils.env.builder.build_env(static: dict[str, str], repo_root: Path, *, comments: dict[str, str] | None = None) → EnvBuilder

Compose the full env-set from static (parsed default.env) + runtime context resolved against repo_root.

comments is the parsed per-key comment map from default.env (see utils.env.parser.parse_static_env_with_comments()). Dynamic keys carry their comments via each handler’s COMMENT constant. custom.env overrides run after every handler (see apply_custom_env()); only INFINITO_IP_RANGE is derived after them, because it follows the final INFINITO_SUBNET a worktree pins there.

utils.env.loader module

Idempotent .env loader for Python CLI entry-points.

utils.env.loader.load_dotenv_once(start: Path | None = None) → Path | None

Source .env into os.environ exactly once per process.

Mirrors the bash scripts/meta/env/load.sh semantics:

  • Honours INFINITO_ENV_LOADED=1 and returns immediately when set.

  • Caller-set values win over .env defaults (setdefault).

  • Walks up from start (default: current working directory) until a .env is found; returns None if none exists in any parent.

utils.env.parser module

Parse the project’s default.env.

The format is the docker-compose .env-subset: flat KEY=value lines, # for comments, optional surrounding double/single quotes for values that contain whitespace or special characters. Anything more exotic (nested mappings, multiline values, variable expansion) is rejected so drift between the file and its consumers stays loud.

Comments are first-class: every # … line directly above a key is captured and surfaced via parse_static_env_with_comments(), so the generator can preserve per-key documentation in the produced .env.

utils.env.parser.env_setting(key: str) → str

One env setting: the process environment wins, default.env is the SPOT behind it.

The fallback is not a default – the value still comes from the single source, just read directly instead of through a generated .env. It is what lets a CLI run outside scripts/meta/env/load.sh without either inventing a value or dying on a key the repository does declare.

Raises:

KeyError – the key is declared nowhere. A budget or filter input that exists in no source must fail loudly, not resolve to "".

utils.env.parser.parse_static_env(path: Path) → dict[str, str]

Return the KEY: value map declared in path.

utils.env.parser.parse_static_env_with_comments(path: Path) → tuple[dict[str, str], dict[str, str]]

Return (values, comments) for the env-file at path.

A key’s comment is the most recent contiguous block of # … lines directly above the KEY=… line, joined with single spaces. Section headers (# — … —) are treated as separators: they reset the pending comment so the next key starts fresh, instead of inheriting the heading line as its own documentation.

utils.env.runtime module

Runtime-context lookups for the .env generator.

Each helper resolves a single piece of information from the host the generator runs on (disk free space, RAM, hostname, /proc/version, GitHub Actions env vars, …). They are intentionally tiny and side-effect-free apart from the OS read they need to perform, so they can be exercised independently in tests.

utils.env.runtime.detect_gha_act() → tuple[bool, bool]

Return (running_on_github, running_on_act).

Mirrors the legacy scripts/meta/env/runtime.sh logic:
  • GITHUB_ACTIONS=true AND ACT=true -> act (local nektos act)

  • GITHUB_ACTIONS=true AND not ACT -> real github actions

utils.env.runtime.df_avail_gb(path: str) → int

Return free space in GB at path (or the closest existing ancestor). 0 when df fails or the output is unparseable.

utils.env.runtime.hostname() → str

socket.gethostname() with a local fallback for sandboxed hosts that fail the syscall.

utils.env.runtime.is_user_writable(path: str) → bool

Return True when path (or its closest existing ancestor) can be written to by the current user without privilege escalation.

Used to decide between a system path (e.g. /opt/venvs) and a user-local fallback ($HOME/.venvs) when the system path is not yet prepared on a fresh dev machine.

utils.env.runtime.is_wsl2() → bool

True when /proc/version mentions microsoft or wsl. False otherwise.

utils.env.runtime.mem_available_mb() → int

MemAvailable from /proc/meminfo in MB. 0 on failure.

utils.env.runtime.mem_stall_pct() → float

full avg60 from /proc/pressure/memory in percent. 0.0 on failure.

utils.env.runtime.mem_total_mb() → int

MemTotal from /proc/meminfo in MB. 0 on failure.

utils.env.runtime.run_helper(cmd: list[str], cwd: Path, extra_env: dict[str, str] | None = None) → str

Run an existing shell helper, return stripped stdout. Empty string on failure. Helpers run with cwd as their working directory.

utils.env.writer module

Serialise an EnvBuilder to .env on disk.

The output format is the docker-compose .env-subset that is also sourceable from bash (via set -a; source .env; set +a). Values that contain only “safe” characters are emitted bare; everything else is double-quoted with backslash-escaping of ` and `”.

Each key is preceded by its documentation comment when the builder carries one, mirroring the convention used in default.env.

utils.env.writer.quote_for_dotenv(value: str) → str
utils.env.writer.write_dotenv(eb: EnvBuilder, dest: Path) → None

Module contents

Project .env generator – internal helpers.

The CLI entry point lives at cli.meta.env (python -m cli.meta.env or make dotenv). It reads the committed default.env, layers runtime context on top (distro, GHA/Act flags, df/meminfo-derived sizes, sha256 secrets, repo owner/name resolution), and writes the resulting .env to the repo root.