State
Some operations related to the project may be stateful - for example any setup performed by bootstrapping operations only needs to be executed on a fresh checkout or whenever the setup process is changed. Blockwork offers a mechanism to persist variables that can then be retrieved in later invocations.
Persisted variables are separated into different namespaces, and different tools can register their own namespaces if required. For example, the bootstrap state is preserved into a namespace called 'bootstrap'.
Each namespace is serialised to JSON, and reloaded lazily - avoiding unnecessary
delays when invoking the Blockwork command as only the state which is required
will be read from disk. Serialised data will be stored into the directory set by
state_dir
in the !Blockwork configuration.
For most usecases, state will be access via the context object that is passed
into different routines. For example, the bootstrap
stage shown in the example below accesses the state dictionary via the context
argument:
The instance of the State
class is accessed via context.state
- this is the
correct way to manage state in most cases (as opposed to manually creating an
instance of State
). Different state namespaces are accessed by using the .
operator - for example context.state.tool_a
opens a namespace called tool_a
,
automatically creating it if it doesn't already exist. Namespaces can alternatively
be accessed using the get
method - for example context.state.get("tool_a")
.
Each namespace is an instance of the StateNamespace
class, and variables can
be similiarly set and retrieved using the .
operator or the set
and get
methods - examples of both methods are shown below:
# Reading a value
existing = context.state.my_tool.some_var
if existing is not None:
print(f"An existing value was already set: {existing}")
# Writing a value
context.state.my_tool.some_var = 123
# Reading a value
existing = context.state.my_tool.get("some_var")
if existing is not None:
print(f"An existing value was already set: {existing}")
# Writing a value
context.state.my_tool.some_var.set("123")
Warning
State variables may only have primitive types such as string, integer, float,
and boolean - using any other type will raise an exception. Namespaces are
also shallow, so do not support deep variable hierarchies (i.e. only
context.state.my_tool.some_var
is supported and not
context.state.my_tool.lvl_one.lvl_two.some_var
).