BuildPlanner

class selene_core.build_utils.planner.BuildPlanner

Manages a list of ArtifactKinds and Steps to convert between them, for the purpose of planning a build process. The internal representation is a directed multi-graph, where each node represents an ArtifactKind, and each edge represents a Step.

Each step has a get_cost implementation that is provided the build context, which allows for determining the optimal (lowest cost) path between two artifact kinds (e.g. the user’s input program and the final selene simulation binary). This allows extensions to add new steps with lower costs to supplant existing steps, or to alter the effective ‘cost’ of their steps based on build context (e.g. user-provided choices, or platform-specific steps).

Each artifact kind has a matches method, which is used to determine the ‘kind’ of a given resource (e.g. the user’s input program). These are checked from highest to lowest priority, allowing extensions to supplant or specialise existing kinds by adding a new kind with higher priority.

__init__()
add_kind(kind: type[ArtifactKind])

Add a new artifact kind to the planner. This represents some resource, such as a file or variable, that can be processed (via a Step) to produce another resource.

add_step(step: type[Step])

Add a step to the planner. This step will be used to convert between two artifact kinds.

At the moment, we also only support steps that accept a single artifact kind and produce a single output kind. This may change in future.

Steps have an associated cost, which is used to determine the optimal path from some input kind to a required output kind (e.g. the final selene simulation binary for the input program). If you wish to override an existing build path, you can do so by adding new steps with lower costs. Alternatively, you can override the input kind and add custom steps to it.

get_optimal_steps_between(input_kind: type[ArtifactKind], output_kind: type[ArtifactKind], build_ctx: BuildCtx) list[Step]

Given an input kind and an output kind, return the optimal path of steps between them. This is done by finding the shortest path in the step graph, using the cost of each step as the weight of the edge in the graph.

If no path is found, an exception is raised. This could mean that the input and/or output kind has not been registered with this planner, or that they are disconnected in the step graph.

identify_kind(resource: Any) type[ArtifactKind] | None

Given some resource (of any type), try to determine the associated ArtifactKind using each registered kind’s matches method, returning the highest priority kind that matches the resource.

If you wish to “override” a kind, e.g. to replace it to add custom steps, or to specialise it, you can do so by adding a new kind with higher priority. It will then be checked first, and successful matching will prevent checking against the original kind.

write_dot(path: Path, highlighted_steps: list | None = None)

Write the step graph to a dot file. This can be visualised using Graphviz.