Lineage
matchlab.lineage
¶
Lineage algorithms over a plan tree.
Steps hold references to their inputs only (step.parents). There is no registry
and no downstream pointer. "The DAG" is therefore
whatever is reachable upstream from the node you are holding, and every graph
operation is a pure function of a root node.
Nodes are deduplicated by object identity, not by name or config. A node feeding two branches is one object and is visited once (structural sharing), while two structurally identical but distinct nodes are two plan entries.
draw also owns the vocabulary for how a step is doing, meaning StepStatus and
StepState, because the tree is where that vocabulary is read. matchlab.progress
drives it during a collection. Nothing here executes anything.
Classes:
-
StepStatus–Where a step has got to in a collection.
-
StepState–A step's status, and how long it has been in it.
Functions:
-
walk–Return
rootand every transitive input, in topological order. -
number–Map each step in
root's plan to the position it is known by. -
draw–root's sub-plan as an indented tree. Seerender, which this joins up. -
render–Render
root's sub-plan as an indented tree, inputs nested beneath consumers.
StepStatus
¶
Bases: StrEnum
flowchart TD
matchlab.lineage.StepStatus[StepStatus]
click matchlab.lineage.StepStatus href "" "matchlab.lineage.StepStatus"
Where a step has got to in a collection.
CACHED, DONE and REFRESHED all mean the artifact is available. They differ
in why.
DONE and REFRESHED both paid for the artifact. A DONE step ran because
something it depends on moved. A REFRESHED step ran because it cannot be cached
at all, and it will run again next time.
Attributes:
StepState
¶
Bases: BaseModel
flowchart TD
matchlab.lineage.StepState[StepState]
click matchlab.lineage.StepState href "" "matchlab.lineage.StepState"
A step's status, and how long it has been in it.
Methods:
-
annotation–The trailing detail shown after a step in a drawing, possibly empty.
Attributes:
-
model_config– -
status(StepStatus) – -
elapsed(float | None) –
walk
¶
Return root and every transitive input, in topological order.
Upstream steps always precede the steps that consume them, so executing the returned list in order satisfies every dependency. Implemented as an iterative depth-first post-order over the parent references.
number
¶
Map each step in root's plan to the position it is known by.
A step is referred to by position, in logs, in draw(), and in a document.
The position belongs to the walk rather than to the step: the
same node numbers differently in walk(deduped) and walk(companies), so nothing
is written back onto the steps. Callers that need one hold this mapping, as
draw does and as matchlab.progress.Progress does for the walk collect gave it.
Returns:
draw
¶
root's sub-plan as an indented tree. See render, which this joins up.
render
¶
render(root: Step, state: Mapping[int, StepState] | None = None, *, markup: bool = False) -> tuple[list[str], dict[int, int]]
Render root's sub-plan as an indented tree, inputs nested beneath consumers.
Each node carries its position, the index collect runs it at, and the index
it occupies in this plan's document. The index is the cross-reference, where
step 7 is the node drawn as [7]. Positions come from walk, not from the order
these lines happen to be printed in, since a tree nests consumers above their
inputs while a walk lists inputs first.
Parameters:
-
(root¶Step) –The step to draw, along with everything upstream of it.
-
(state¶Mapping[int, StepState] | None, default:None) –Per-step status, keyed by
id(step)asnumberis. Steps missing from the mapping are drawn asPENDING. When omitted, each step is drawn from its ownis_collectedflag instead, a static view of a plan you hold. -
(markup¶bool, default:False) –Emit Rich markup, styling each marker and annotation by status. Off by default, so the return value stays printable anywhere.
Returns:
-
list[str]–The lines, one per node plus one per repeat reference, and the row each step
-
dict[int, int]–is first drawn on, keyed by
id(step)asnumberis. The rows are what let a -
tuple[list[str], dict[int, int]]–caller show part of a tree and still know where it is:
matchlab.progress -
tuple[list[str], dict[int, int]]–windows a plan too tall for the terminal around the row that is running.
A node feeding several branches is expanded where it is first met and marked ↑
everywhere after, rather than having its whole subtree redrawn each time. Positions
are what make that readable. ↑ [12] names the node you already have, and without
it the drawing contradicts the structural sharing it is meant to show. The
24-step plan in examples/companies draws 187 lines expanded, and 39 like this.