All docs
Example: a node variant
A coexist load step remains independently addable alongside its base node; project variant choices are explicit and persisted.
Sometimes you want to offer a different implementation of an existing node — a domain-specific
version of a generic one. overrides="pkg.node" registers your step as a variant of that node
identity; override_mode decides whether it replaces the original or coexists with it.
The code#
# tool.py
from lsdtools import Tool, Source, Table
tool = Tool("mim_openpit", label="Open Pit")
@tool.load(overrides="mim.solid", override_mode="coexist", source_kinds=("file",))
def pit_shell(src: Source, bench_height: float = 15.0) -> Table:
"""Build a pit-shell solid from survey points — a variant of the base `mim.solid` node."""
t = src.read()
bench = t["z"] / bench_height # a whole-column expression
return t.with_column("bench", bench)
What each line does#
- Node identity is always
f"{tool_name}.{fn_name}". The base node here ismim.solid— thesolidstep of a tool namedmim(thelsd-mimpackage). overrides="mim.solid"— registerspit_shellas a variant of that identity. It does not need to importlsd-mim; it just names the identity.override_mode="coexist"— both stay addable under their own identities. The basemim.solidremains the base;mim_openpit.pit_shellis a separate step choice. It cannot be selected as a replacement provider. Declaringoverride_mode="replace"instead makes the provider eligible to stand in for the base identity; a sole replacer becomes the default, while multiple replacers require an explicit project selection.pit_shell's body — a normal load: read the picked file, then add abenchcolumn derived fromz.t["z"] / bench_heightis a single-kernelColumnexpression.
Run it in Python#
Because it coexists, pit_shell is a fully-functional load on its own:
from lsdtools import Engine, Source, Table
Table({"x": [0.0], "y": [0.0], "z": [30.0]}).write_csv("survey.csv")
Engine().run(pit_shell(Source.file("survey.csv"), bench_height=15.0)).output.print()
# → x y z bench
# 0 0 30 2
To record that a project should retain the base identity with overrides independently addable,
call Engine.set_variant:
with Engine.load("pit.lsd") as eng:
eng.set_variant("mim.solid", mode="coexist")
eng.save()
This block requires an existing saved project and both providers to be loaded. Engine.load(path)
opens that document; the removed Engine(path) constructor form does not. Coexist selections must
omit provider. If you change the package declaration to override_mode="replace" and load it in
a fresh process, a project can select it with
eng.set_variant("mim.solid", mode="replace", provider="mim_openpit"). The provider key is the
Tool's name, not the step's full identity. The coexist declaration shown above rejects that call.
Where the user picks it#
The old Desktop Package Manager Variants dropdown is removed. Current
Project Packages provides package activation and status. Use the Python
workflow above for an explicit project variant choice; saving records it in the .lsd document's
package_state.variants. Engine.set_variant validates the choice and reinstantiates affected
live steps within that engine.
Try changing it#
- Switch to
override_mode="replace"and reopen the project — existingmim.solidnodes adopt your step with no re-wiring. - Override a shape instead:
@tool.shape(overrides="mim.wireframe", override_mode="coexist"). - Add a
bench_heightvalidation rule via adialog=so the value can't be zero.
Related#
Learn — Node variants · The Package Manager · Load steps
API — Engine · Tool · PackageManager
Examples — A complete package · File loader