_stage
_stage
¶
Stage-line rendering — one format, one colour palette, one column width.
The setup aggregator prints one <label> <marker> (<detail>)
line per phase. Frontends (terok's terok setup,
terok-executor CLIs, future CI reporters) can mix stage lines of
their own — desktop-entry install, credential-DB purge, etc. — by
importing the public symbols from terok_sandbox; keeping the
renderer central guarantees the mixed log reads as one continuous
column with aligned status markers and coherent colours.
Kept as an underscore-prefixed submodule because the package's
__init__ already re-exports the surface — a public
terok_sandbox.stage submodule name would collide with the
re-exported stage() function.
Colour is auto-detected from NO_COLOR / FORCE_COLOR /
sys.stdout.isatty() (the no-color.org contract). Terminals that
don't report TTY — typical CI logs — fall through to plain text.
STAGE_WIDTH = 21
module-attribute
¶
Marker
¶
StageLine(label)
¶
Context-managed progressive stage line.
Couples stage_begin and stage_end at one call site
so the begin/end pairing is structurally visible — a missing or
misplaced end becomes impossible rather than a bug waiting to
happen.
Use like::
with stage_line("Vault") as s:
do_work() # slow; label shows immediately
s.ok("systemd, socket, reachable") # marker + detail
Set the marker via ok, warn, fail,
missing, or skip; only the most recent call wins
(the single-line output has room for one marker). The caller can
return early — the context manager's __exit__ still runs
and emits whatever marker was last set.
Exception paths: if an exception escapes the with block the
line is always completed as FAIL (<exception>) — an uncaught
exception dominates any marker the caller set earlier. This
catches the "optimistic early marker" bug where a caller writes
s.ok("reachable") before a final check that turns out to
raise; without this precedence rule the log would misleadingly
read ok while the actual run failed. Callers that want their
own message in the log should catch the exception, call
fail with the wanted detail, and return normally — that
path emits the caller's message with no exception to contend with.
A block that exits with no marker set and no exception is a
caller bug; the line is completed as FAIL (no marker set) to
make the omission loud rather than leaving the label column
dangling mid-line.
Capture label; deferred rendering until __enter__.
Source code in src/terok_sandbox/_stage.py
__enter__()
¶
__exit__(_exc_type, exc, _tb)
¶
Emit the line: exception (if any) wins over stored marker; never suppresses.
Source code in src/terok_sandbox/_stage.py
ok(detail='')
¶
warn(detail='')
¶
fail(detail='')
¶
missing(detail='')
¶
stage(label, marker, detail='')
¶
Write one complete stage line: ' <label> <marker>[ (<detail>)]'.
Matches stage_begin + stage_end when the caller
doesn't need progressive output. The marker is ANSI-coloured
according to _PALETTE when colour is enabled.
Multi-line detail is split: only the first line lands inside the
parentheses; remaining lines are emitted as an indented
continuation block underneath. See stage_end for the
rationale (callers passing a multi-line exception str()).
Source code in src/terok_sandbox/_stage.py
stage_begin(label)
¶
Write the label column and flush — no newline, no marker.
Pairs with stage_end. Use when the phase takes long enough
that the operator benefits from seeing which step is running
before the marker lands. Without this, a slow
systemctl --user restart looks like a frozen terminal.
Source code in src/terok_sandbox/_stage.py
stage_end(marker, detail='')
¶
Write the marker and optional detail with trailing newline.
The sibling of stage_begin; together they render the same
line stage would.
Multi-line detail is split: only the first line lands inside the
parentheses on the marker line; the remainder is emitted as an
indented continuation block underneath. This guards against
callers passing exception str() whose help text spans several
lines (e.g. a SystemExit carrying paths and remediation hints)
— without the split, the dotted-column layout smears across the
log and the closing paren lands on the last line of help text.
Source code in src/terok_sandbox/_stage.py
stage_line(label)
¶
Return a StageLine context manager for progressive rendering.
Thin factory so the call site reads with stage_line("Vault") as
s: rather than the class name.
Source code in src/terok_sandbox/_stage.py
supports_color()
¶
Return whether ANSI colour should be emitted to stdout.
Follows the no-color.org <https://no-color.org>_ contract:
NO_COLOR always wins; FORCE_COLOR (set to anything but
"0") opts back in even on non-TTY streams; otherwise
sys.stdout.isatty() decides. Cached at module-import time so
the verdict is stable for the life of the process — tests that
need a different answer set the env vars before importing.
Source code in src/terok_sandbox/_stage.py
bold(text)
¶
Return text wrapped in ANSI bold when supports_color is true.