scistudio.blocks.code
Canonical import root: from scistudio.blocks.code import ...
Self-contained public-API reference — 60 symbols from this module's __all__, with signatures and docstrings inlined (ADR-052 §7). Generated; do not hand-edit.
CodeBlock — class
Stability: provisional · Since 0.3.1
class CodeBlock(Block)
CodeBlock(config: 'dict[str, Any] | None' = None) -> 'None'
Run a project-local script as a workflow step, exchanging data via files.
Use the Code Block when you have a working script (Python, R/Quarto, shell, MATLAB/Octave, or a Jupyter notebook) and want to run it inside a workflow without porting it to a SciStudio block. You point the block at a script in your project and declare which inputs it reads and which outputs it writes. The interpreter is chosen automatically from the script's file extension.
How data flows:
- Inputs: the runtime writes each declared input to a file in the run's
inputs/folder before the script starts. The defaultdatainput port accepts any data object; you can add more named input ports. - Outputs: the script writes files into the run's
outputs/folder, which the runtime reads back into typed data objects. The defaultresultoutput port returns any data object; you can add more named output ports. - Your script finds these folders through the
SCISTUDIO_*environment variables the runtime sets for it.
Configuration highlights (see CodeBlockConfig for the full set):
script_path (required) points at the project-local script; inputs
and outputs declare the file-exchange ports; interpreter_mode and
interpreter_path choose between an auto-detected interpreter and an
explicit one.
Example: >>> block = CodeBlock({"script_path": "scripts/analyse.py"}) >>> block.name 'Code Block'
Members
run(self, inputs: 'dict[str, Collection]', config: 'BlockConfig') -> 'dict[str, Collection]'—provisional· Since0.3.1— Run the configured script and return its declared outputs.
CodeBlockBackend — protocol
Stability: provisional · Since 0.3.1
class CodeBlockBackend(Protocol)
CodeBlockBackend(*args, **kwargs)
Interface an interpreter backend must implement to run Code Block scripts.
A backend teaches the Code Block how to run scripts written in one language
family (Python, R/Quarto, shell, MATLAB/Octave, or Jupyter notebooks). Each
backend declares the file extensions it owns, decides whether it can run a
given script, resolves the interpreter command, and launches the process.
Register your own backend with register_codeblock_backend to add a
new language without changing the Code Block itself.
Example: >>> class JuliaBackend: ... name = "julia" ... extensions = frozenset({".jl"}) ... def supports(self, script_path, config): ... return script_path.suffix.lower() in self.extensions ... def resolve(self, context): ... ... def run(self, context, interpreter): ... >>> register_codeblock_backend(JuliaBackend())
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether this backend can run the script at script_path.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — Resolve the interpreter command and environment for a run.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Launch the resolved interpreter and return the finished process.
CodeBlockConfig — class
Stability: provisional · Since 0.3.1
class CodeBlockConfig(BaseModel)
The saved settings for one Code Block: script, interpreter, and ports.
This is the full set of fields a Code Block stores. The only required field
is script_path; the rest have sensible defaults. The inputs and
outputs lists declare the file-exchange ports the script reads and
writes (see PortFileConfig).
The code and inline_code fields are accepted only so an old
inline-code configuration fails with a clear migration message instead of an
opaque "unexpected field" error.
Example: >>> config = CodeBlockConfig( ... script_path="scripts/analyse.py", ... outputs=[ ... PortFileConfig( ... name="result", direction="output", ... data_type="DataFrame", extension="csv", ... ) ... ], ... ) >>> config.interpreter_mode 'auto'
Members
resolve_script_path(self, project_dir: 'Path') -> 'Path'— unmarked — see the module source / ADR-052 — Resolvescript_pathto an absolute path inside the project.resolve_working_directory(self, project_dir: 'Path') -> 'Path'— unmarked — see the module source / ADR-052 — Resolveworking_directoryto an absolute path inside the project.resolve_exchange_root(self, project_dir: 'Path') -> 'Path'— unmarked — see the module source / ADR-052 — Resolveexchange_rootto an absolute path inside the project.
CodeBlockConfigError — exception
Stability: provisional · Since 0.3.1
class CodeBlockConfigError(ValueError)
Raised when a Code Block configuration is invalid.
Examples: pasted inline code where a script path is required, an entry
function that the Code Block does not call, a script or folder path that
escapes the project directory, or interpreter_mode="existing" without an
interpreter_path.
CodeBlockExchangeError — exception
Stability: provisional · Since 0.3.1
class CodeBlockExchangeError(RuntimeError)
CodeBlockExchangeError(message: 'str', diagnostics: 'Sequence[ExchangeDiagnostic]') -> 'None'
Raised when preparing inputs or collecting outputs hits a blocking error.
Carries the diagnostics that caused the failure (for example a required input with no value, or a required output the script never wrote).
CodeBlockExchangeLayout — class
Stability: provisional · Since 0.3.1
class CodeBlockExchangeLayout
CodeBlockExchangeLayout(*, exchange_dir: 'Path', inputs_dir: 'Path', outputs_dir: 'Path', manifest_path: 'Path', logs_dir: 'Path', temp_dir: 'Path') -> None
The set of folders and files that make up one run's exchange directory.
Every Code Block run gets its own exchange folder with fixed subfolders for inputs, outputs, logs, and scratch files, plus a manifest file recording what happened. This describes where each of those lives on disk.
CodeBlockExchangeManifest — class
Stability: provisional · Since 0.3.1
class CodeBlockExchangeManifest
CodeBlockExchangeManifest(*, layout: 'CodeBlockExchangeLayout', ports: 'dict[tuple[PortDirection, str], PortManifestRecord]', diagnostics: 'list[ExchangeDiagnostic]' = <factory>) -> None
The full record of one Code Block run's exchange: folders, ports, issues.
The manifest ties together the run's folder layout, one record per declared
port, and any warnings or errors. Ports are keyed by (direction, name)
so a block declaring an input and an output with the same name (such as
data in and data out) keeps both. The input_folders and
output_folders views are keyed by plain port name, which is unique
within a single direction.
Members
input_folders(self) -> 'dict[str, Path]'— unmarked — see the module source / ADR-052 — Map each input port name to its on-disk folder.output_folders(self) -> 'dict[str, Path]'— unmarked — see the module source / ADR-052 — Map each output port name to its on-disk folder.to_dict(self) -> 'dict[str, object]'— unmarked — see the module source / ADR-052 — Return the whole manifest as a JSON-serialisable dictionary.
CodeBlockExchangePort — class
Stability: provisional · Since 0.3.1
class CodeBlockExchangePort
CodeBlockExchangePort(*, name: 'str', direction: 'PortDirection', data_type: 'type[DataObject] | str' = <class 'scistudio.core.types.base.DataObject'>, extension: 'str', capability_id: 'str | None' = None, required: 'bool' = True, folder_name: 'str | None' = None) -> None
A single Code Block port, resolved for use by the exchange runtime.
This is the runtime view of one declared input or output port: the data
type is a resolved class (not just a name), and the target folder is
settled. The Code Block builds these from the saved PortFileConfig
entries before preparing the exchange folders.
CodeBlockExecutionError — exception
Stability: provisional · Since 0.3.1
class CodeBlockExecutionError(RuntimeError)
CodeBlockExecutionError(message: 'str', *, returncode: 'int', stdout: 'str', stderr: 'str') -> 'None'
Raised when the script's interpreter process exits with an error.
The Code Block treats any non-zero exit code from the launched script as a failure and raises this, attaching the script's captured output so you can diagnose what went wrong.
CodeBlockMigrationError — exception
Stability: provisional · Since 0.3.1
class CodeBlockMigrationError(ValueError)
CodeBlockMigrationError(diagnostics: 'list[MigrationDiagnostic]') -> 'None'
Raised when an old-style Code Block config cannot be run as-is.
Earlier Code Blocks could hold pasted inline code or call a named entry function. Those forms are no longer run; this error explains what needs to change (save the code as a project-local script that exchanges data through files) and carries one diagnostic per problem found.
CodeBlockProvenancePayload — class
Stability: provisional · Since 0.3.1
class CodeBlockProvenancePayload(BaseModel)
The complete provenance record stored for one Code Block run.
Bundles the script identity, interpreter and environment snapshot, timing, the file-format handlers used per port, and the exchange manifest into one record kept with the run's lineage.
CodeBlockRuntimeContext — class
Stability: provisional · Since 0.3.1
class CodeBlockRuntimeContext
CodeBlockRuntimeContext(config: 'CodeBlockConfig', script_path: 'Path', project_dir: 'Path', exchange_dir: 'Path', environment_config: 'Mapping[str, Any]') -> None
Everything a backend needs to resolve and launch one script run.
The Code Block builds this read-only bundle once per run and hands it to
the selected backend's CodeBlockBackend.resolve and
CodeBlockBackend.run methods. It names the script to run, where the
project lives, and the exchange folder where the runtime wrote the declared
inputs and expects the declared outputs.
CodeBlockTimeoutError — exception
Stability: provisional · Since 0.3.1
class CodeBlockTimeoutError(TimeoutError)
CodeBlockTimeoutError(message: 'str', *, timeout_seconds: 'float', stdout: 'str | None', stderr: 'str | None') -> 'None'
Raised when a Code Block script runs longer than its allowed time.
A Code Block can set a wall-clock time limit for its script. When the launched interpreter process exceeds that limit it is stopped and this error is raised, carrying whatever the script printed before it was killed so you can see how far it got.
Example: >>> try: ... run_codeblock_process( ... argv=["python", "slow.py"], ... cwd=Path("."), ... env_delta={}, ... timeout_seconds=1.0, ... ) ... except CodeBlockTimeoutError as err: ... print(err.timeout_seconds, err.stderr)
CodeBlockValidationDiagnostic — class
Stability: provisional · Since 0.3.1
class CodeBlockValidationDiagnostic
CodeBlockValidationDiagnostic(field: 'str', message: 'str', severity: 'str' = 'error', port_name: 'str | None' = None) -> None
One problem found in a Code Block configuration, ready to show a user.
Names the config field (and port, when relevant), explains what is wrong in
plain language, and says whether it blocks the run ("error") or is only
advisory ("warning").
Members
render(self, *, node_id: 'str | None' = None) -> 'str'— unmarked — see the module source / ADR-052 — Format this diagnostic as a one-line message for the workflow editor.
EnvironmentSnapshot — class
Stability: provisional · Since 0.3.1
class EnvironmentSnapshot(BaseModel)
Best-effort record of the interpreter and environment a script ran in.
Captures which interpreter was used and how it was chosen, so a run can be understood and re-created afterwards.
ExchangeDiagnostic — class
Stability: provisional · Since 0.3.1
class ExchangeDiagnostic
ExchangeDiagnostic(*, severity: 'DiagnosticSeverity', code: 'str', message: 'str', port_name: 'str | None' = None, path: 'Path | None' = None) -> None
One warning or error raised while preparing or collecting exchange files.
Examples: a required input had no value, a required output produced no file,
or the script left an unexpected file in the outputs folder. The Code Block
fails the run when any diagnostic has "error" severity.
Members
to_dict(self) -> 'dict[str, str | None]'— unmarked — see the module source / ADR-052 — Return this diagnostic as a JSON-serialisable dictionary.
ExchangeFileRecord — class
Stability: provisional · Since 0.3.1
class ExchangeFileRecord
ExchangeFileRecord(*, port_name: 'str', direction: 'PortDirection', path: 'Path', object_type: 'str', format_hint: 'str', status: 'ManifestStatus', capability_id: 'str | None' = None, warning: 'str | None' = None) -> None
One file in the manifest: a written input or a discovered output.
The manifest keeps one of these per file so a run can be traced after the fact: which port the file belongs to, where it is, what it holds, and whether it was written, collected, or ignored.
Members
to_dict(self) -> 'dict[str, str | None]'— unmarked — see the module source / ADR-052 — Return this record as a JSON-serialisable dictionary.
InterpreterFamily — type-alias
Stability: unmarked — see the module source / ADR-052
type-alias — see the module source for the value.
InterpreterResolutionError — exception
Stability: provisional · Since 0.3.1
class InterpreterResolutionError(RuntimeError)
Raised when no safe interpreter command can be built for a script.
Common causes: the configured interpreter path does not exist, no suitable interpreter is found on the system path, or a required setting is missing.
LazyList — class
Stability: provisional · Since 0.3.1
class LazyList
LazyList(collection: 'Collection') -> 'None'
A list-like view over a Collection that loads items only when needed.
Wraps a Collection and behaves like a list for a user script, but
keeps data on disk until you touch it. Iterating yields one item at a time
(roughly constant peak memory), indexing loads only the requested item, and
len() returns the count without reading any data. Reach for
to_list only when you really need every item in memory at once.
Args: collection: The Collection whose items this list-like view exposes.
Example: >>> items = LazyList(collection) >>> len(items) # no data loaded 3 >>> first = items[0] # loads only item 0 >>> for item in items: # loads one item at a time ... process(item)
Members
to_list(self) -> 'list[Any]'— unmarked — see the module source / ADR-052 — Load all items into memory and return as a plain list.
MaterialiseAdapter — protocol
Stability: provisional · Since 0.3.1
class MaterialiseAdapter(Protocol)
MaterialiseAdapter(*args, **kwargs)
A function that writes one data object into an input folder as a file.
The Code Block calls a materialise adapter for each input it needs to hand to a script, turning an in-memory data object into a file the script can read. Supplying your own adapter lets you control how data types are written to disk.
MatlabCodeBlockBackend — class
Stability: provisional · Since 0.3.1
class MatlabCodeBlockBackend
Run a Code Block script written for MATLAB or Octave (.m, .mlx).
This backend runs MATLAB-family scripts. For a .m script it prefers
MATLAB and falls back to Octave when MATLAB is not installed; a .mlx
live script requires MATLAB. You can pin a specific interpreter with the
Code Block's interpreter_mode / interpreter_path settings. The
process runs in the per-run exchange folder, where it reads its declared
inputs and writes its declared outputs.
Example: >>> backend = MatlabCodeBlockBackend() >>> sorted(backend.extensions) ['.m', '.mlx'] >>> backend.supports(Path("model.mlx"), config) True
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether script_path is a MATLAB-family script this backend runs.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — Resolve a MATLAB or Octave interpreter and build its launch command.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Launch MATLAB or Octave on the script and return the finished process.
MatlabRuntimeResolutionError — exception
Stability: provisional · Since 0.3.1
class MatlabRuntimeResolutionError(InterpreterResolutionError)
Raised when no usable MATLAB or Octave interpreter can be selected.
Common causes: neither MATLAB nor Octave is installed on the system path,
a configured interpreter path does not exist, or a MATLAB live script
(.mlx) is paired with Octave, which cannot run live scripts.
NotebookCodeBlockBackend — class
Stability: provisional · Since 0.3.1
class NotebookCodeBlockBackend
NotebookCodeBlockBackend(executable_locator: 'Callable[[str], str | None] | None' = None) -> 'None'
Run a Code Block script that is a Jupyter notebook (.ipynb).
This backend executes a notebook end to end with Jupyter nbconvert and
saves the run notebook as an output artifact, so you can use a notebook as a
workflow step. It needs Jupyter nbconvert available, either auto-detected
on the system path or pinned through the Code Block's interpreter_mode /
interpreter_path settings. The notebook's kernel launches from the
project root and reads and writes the declared input and output folders.
Args:
executable_locator: Optional function that finds an executable by name
(defaults to shutil.which). Mainly useful for testing.
Example: >>> backend = NotebookCodeBlockBackend() >>> backend.supports(Path("report.ipynb"), config) True
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether script_path is a notebook this backend runs.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — Resolvenbconvertand build the command that executes the notebook.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Execute the notebook in place and return the finished process.
OutputDiscoveryResult — class
Stability: provisional · Since 0.3.1
class OutputDiscoveryResult
OutputDiscoveryResult(*, files_by_port: 'dict[str, list[Path]]', diagnostics: 'list[ExchangeDiagnostic]') -> None
What an output-folder scan found, before files are read back into objects.
Returned by discover_declared_outputs: the files matched for each
output port and any issues (missing required outputs, extension mismatches,
stray files) found while scanning.
Members
has_errors(self) -> 'bool'— unmarked — see the module source / ADR-052 — Whether any diagnostic is an error.
PortFileConfig — class
Stability: provisional · Since 0.3.1
class PortFileConfig(BaseModel)
How one Code Block port maps a named input or output to files on disk.
A Code Block script does not pass data by argument; it reads and writes
files. Each declared port says what kind of data it carries, what file
extension to use, and which folder under the exchange directory to read from
or write to. One PortFileConfig describes a single input or output port.
Example: >>> PortFileConfig( ... name="spectra", ... direction="input", ... data_type="DataFrame", ... extension="csv", ... ).exchange_folder 'inputs/spectra/'
PortManifestRecord — class
Stability: provisional · Since 0.3.1
class PortManifestRecord
PortManifestRecord(*, name: 'str', direction: 'PortDirection', object_type: 'str', folder: 'Path', format_hint: 'str', capability_id: 'str | None', required: 'bool', status: 'ManifestStatus' = 'planned', files: 'list[ExchangeFileRecord]' = <factory>, warnings: 'list[str]' = <factory>) -> None
The manifest entry for one declared port and the files it gathered.
Each declared input or output port has one of these in the manifest. It records the port's folder and expected data type, its current state, and the files written to or discovered in that folder.
Members
to_dict(self) -> 'dict[str, object]'— unmarked — see the module source / ADR-052 — Return this port record as a JSON-serialisable dictionary.
PythonCodeBlockBackend — class
Stability: provisional · Since 0.3.1
class PythonCodeBlockBackend
Run a Code Block script written in Python (.py).
This is the default Code Block backend. It picks a Python interpreter
(either the one bundled with the app or an explicit path you configure via
interpreter_mode / interpreter_path), launches the script from the
project root, and exposes the SCISTUDIO_* environment variables so the
script can find its declared input and output folders. The script reads its
inputs from files and writes its outputs to files; the Code Block converts
those files back into typed data objects.
Example: >>> backend = PythonCodeBlockBackend() >>> backend.name 'python' >>> backend.supports(Path("analysis.py"), config) True
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether script_path is a Python script this backend runs.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — Resolve the Python interpreter and exchange environment for a run.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Launch the Python interpreter on the script and return the process.
RQuartoCodeBlockBackend — class
Stability: provisional · Since 0.3.1
class RQuartoCodeBlockBackend
Run a Code Block script written in R or Quarto (.R, .Rmd, .qmd).
This backend runs three related kinds of script: a plain R script (.R)
with Rscript, an R Markdown document (.Rmd) rendered with the R
rmarkdown package, and a Quarto document (.qmd) rendered with the
quarto command. It auto-detects Rscript or quarto on the system
path, or uses a path you pin through interpreter_mode /
interpreter_path. The process runs in the per-run exchange folder and
reads and writes the declared input and output folders.
Example: >>> backend = RQuartoCodeBlockBackend() >>> backend.supports(Path("figures.qmd"), config) True
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether script_path is an R or Quarto script this backend runs.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — ResolveRscriptorquartoand build the launch command.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Launch the R or Quarto command and return the finished process.
ReconstructAdapter — protocol
Stability: provisional · Since 0.3.1
class ReconstructAdapter(Protocol)
ReconstructAdapter(*args, **kwargs)
A function that reads one output file back into a data object.
The Code Block calls a reconstruct adapter for each file a script writes to a declared output port, turning it back into a typed in-memory object. Supplying your own adapter lets you control how files are read for each data type.
ResolvedInterpreter — class
Stability: provisional · Since 0.3.1
class ResolvedInterpreter(BaseModel)
The exact command and environment chosen to run one script.
Produced by an interpreter backend, this captures everything needed to launch the script: which executable to run, the full argument list, the working directory, environment overrides, and best-effort version and warning notes for the run's provenance record.
ScriptProvenance — class
Stability: provisional · Since 0.3.1
class ScriptProvenance(BaseModel)
Identity of the exact script that ran, for reproducibility.
Records where the script is, a content hash so you can tell if it changed, its git state, and basic file metadata.
ShellCodeBlockBackend — class
Stability: provisional · Since 0.3.1
class ShellCodeBlockBackend
Run a Code Block script written as a POSIX shell script (.sh).
This backend runs .sh scripts with a POSIX-compatible shell. It tries
sh, bash, dash, then zsh from the system path, or uses a
path you pin through interpreter_mode / interpreter_path (a Windows
System32\bash.exe is rejected as incompatible). The script runs in the
per-run exchange folder and is given SCISTUDIO_CODEBLOCK_* environment
variables pointing at its input, output, project, and script paths.
Example: >>> backend = ShellCodeBlockBackend() >>> backend.supports(Path("convert.sh"), config) True
Members
supports(self, script_path: 'Path', config: 'CodeBlockConfig') -> 'bool'— unmarked — see the module source / ADR-052 — Return whether script_path is a shell script this backend runs.resolve(self, context: 'CodeBlockRuntimeContext') -> 'ResolvedInterpreter'— unmarked — see the module source / ADR-052 — Resolve a POSIX shell and build the launch command and environment.run(self, context: 'CodeBlockRuntimeContext', interpreter: 'ResolvedInterpreter') -> 'subprocess.CompletedProcess[str]'— unmarked — see the module source / ADR-052 — Launch the shell on the script and return the finished process.
UnsupportedScriptExtensionError — exception
Stability: provisional · Since 0.3.1
class UnsupportedScriptExtensionError(InterpreterResolutionError)
Raised when a script's file extension has no interpreter to run it.
allocate_port_folder — function
Stability: provisional · Since 0.3.1
allocate_port_folder(parent: 'Path', port_name: 'str', used_names: 'set[str]', *, create: 'bool' = True) -> 'Path'
Choose a unique folder for one port under parent, avoiding collisions.
Derives a safe folder name from the port name; if that name is already used or already exists on disk, it appends a suffix until it finds a free name, so two ports never share a folder.
Args:
parent: The inputs/ or outputs/ folder to create the port folder in.
port_name: The port's name, used as the basis for the folder name.
used_names: Folder names already taken; updated in place with the choice.
create: When True (the default), create the folder on disk.
Returns: The path of the allocated port folder.
Raises: RuntimeError: If no free folder name can be found.
build_codeblock_provenance_payload — function
Stability: provisional · Since 0.3.1
build_codeblock_provenance_payload(*, script: 'ScriptProvenance', interpreter: 'ResolvedInterpreter', environment: 'EnvironmentSnapshot', started_at: 'str', completed_at: 'str | None' = None, selected_capabilities: 'Mapping[str, str] | None' = None, exchange_manifest: 'Mapping[str, Any] | None' = None) -> 'dict[str, Any]'
Assemble the full provenance record for a run as a JSON-ready dictionary.
Args:
script: Identity of the script that ran.
interpreter: The resolved interpreter command used.
environment: Snapshot of the interpreter and environment.
started_at: Run start time as a UTC timestamp string.
completed_at: Run completion time, or None if it did not finish.
selected_capabilities: The save/load handler chosen per port.
exchange_manifest: The run's exchange manifest as a dictionary.
Returns: The provenance payload as a JSON-serialisable dictionary.
capture_environment_snapshot — function
Stability: provisional · Since 0.3.1
capture_environment_snapshot(resolved_interpreter: 'ResolvedInterpreter', *, mode: 'InterpreterMode', environment_delta: 'Mapping[str, str] | None' = None) -> 'EnvironmentSnapshot'
Build an environment snapshot from a resolved interpreter.
Args:
resolved_interpreter: The interpreter command chosen for the run.
mode: How the interpreter was chosen ("auto" or "existing").
environment_delta: Environment overrides to record; falls back to the
interpreter's own environment when omitted.
Returns:
An EnvironmentSnapshot for the run.
capture_script_provenance — function
Stability: provisional · Since 0.3.1
capture_script_provenance(script_path: 'Path', *, project_dir: 'Path') -> 'ScriptProvenance'
Record a script's identity: its content hash, git state, and metadata.
Args: script_path: Path to the script that ran. project_dir: Absolute path to the project root.
Returns:
A ScriptProvenance describing the script.
codeblock_config_payload — function
Stability: provisional · Since 0.3.1
codeblock_config_payload(config: 'Mapping[str, Any]') -> 'dict[str, Any]'
Extract just the saved Code Block settings from a raw config mapping.
A config may arrive with its fields at the top level or nested under a
params key, and may carry runtime-only keys the runtime injects (such as
the project directory). This returns the script settings only, flattened and
with those runtime-only keys removed.
Args: config: The raw configuration mapping.
Returns: The persisted Code Block settings as a plain dictionary.
codeblock_exchange_env — function
Stability: provisional · Since 0.3.1
codeblock_exchange_env(context: 'CodeBlockRuntimeContext') -> 'dict[str, str]'
Build the SCISTUDIO_* environment variables a script uses to find its files.
A Code Block script does not receive its inputs as function arguments; the runtime writes them to files and the script reads and writes files. These environment variables tell the script where those folders are, so it can locate its declared inputs and write its declared outputs regardless of the language it is written in.
Args: context: The run context whose exchange directory and script path the variables point at.
Returns:
A mapping with the SCISTUDIO_EXCHANGE_DIR, SCISTUDIO_INPUTS_DIR,
SCISTUDIO_OUTPUTS_DIR, and SCISTUDIO_SCRIPT_PATH keys.
collect_codeblock_outputs — function
Stability: provisional · Since 0.3.1
collect_codeblock_outputs(port_configs: 'Sequence[CodeBlockExchangePort]', *, manifest: 'CodeBlockExchangeManifest', reconstruct_adapter: 'ReconstructAdapter') -> 'dict[str, Collection]'
Read the script's output files back into typed collections.
Scans the output folders, then reads each matched file into a data object with reconstruct_adapter and groups them into one collection per output port. Fails if the scan found any blocking error (such as a missing required output).
Args: port_configs: The declared input and output ports for the run. manifest: The run manifest, updated in place during discovery. reconstruct_adapter: Function that reads one file into a data object.
Returns: A mapping from each output-port name to its collection of data objects.
Raises: CodeBlockExchangeError: If output discovery reports a blocking error.
create_codeblock_exchange_layout — function
Stability: provisional · Since 0.3.1
create_codeblock_exchange_layout(exchange_root: 'Path', *, block_id: 'str', run_id: 'str', block_slug: 'str' = 'codeblock', create: 'bool' = True) -> 'CodeBlockExchangeLayout'
Work out (and optionally create) the folders for one Code Block run.
Builds a per-run folder under exchange_root named from the block and run
identifiers, with inputs/, outputs/, logs/, and tmp/
subfolders and a manifest path.
Args:
exchange_root: Root folder that holds all runs' exchange directories.
block_id: Identifier of the block instance, used in the folder name.
run_id: Identifier of this run, used as the per-run subfolder name.
block_slug: Short label prefixed to the block folder name.
create: When True (the default), create the folders on disk; when
False, only compute the paths.
Returns:
The resolved CodeBlockExchangeLayout for the run.
discover_declared_outputs — function
Stability: provisional · Since 0.3.1
discover_declared_outputs(port_configs: 'Sequence[CodeBlockExchangePort]', *, manifest: 'CodeBlockExchangeManifest') -> 'OutputDiscoveryResult'
Scan the output folders for the files the script wrote.
For each output port, lists the files whose extension matches the declared
one. Files with the wrong extension are ignored with a warning; a required
port that produced no matching file records an error; stray files or folders
directly under outputs/ are noted as warnings. The manifest is updated
in place with the files and diagnostics found.
Args: port_configs: The declared input and output ports for the run. manifest: The run manifest, updated in place with discovered files.
Returns: The matched files per output port together with the scan diagnostics.
ensure_codeblock_backends_loaded — function
Stability: provisional · Since 0.3.1
ensure_codeblock_backends_loaded() -> 'None'
Import the built-in backend modules once so they self-register.
Reading the registry through list_codeblock_backends or
resolve_codeblock_backend calls this for you; it does nothing after
the first call.
initialise_exchange_manifest — function
Stability: provisional · Since 0.3.1
initialise_exchange_manifest(port_configs: 'Sequence[CodeBlockExchangePort]', *, layout: 'CodeBlockExchangeLayout') -> 'CodeBlockExchangeManifest'
Create a folder for every declared port and return a starting manifest.
Allocates one folder per port under the inputs or outputs directory and records each as a planned port in a fresh manifest, ready for inputs to be written and outputs to be collected.
Args: port_configs: The declared input and output ports for the run. layout: The run's folder layout.
Returns:
A manifest with one "folder_created" record per port and no files yet.
introspect_script — function
Stability: provisional · Since 0.3.1
introspect_script(script_path: 'str | Path') -> 'dict[str, Any]'
Read a script's structure without running it.
Parses the script's source to learn about its run() and configure()
functions and its top-level docstring. The Code Block tooling uses this to
suggest input ports and a configuration form for a script, so a user does
not have to declare everything by hand. Reading is done by static analysis
only, so the script is never executed.
Args: script_path: Path to the script file to inspect.
Returns: A dictionary with these keys:
- ``has_run`` (bool): whether the script defines a ``run()`` function.
- ``run_params`` (list): one dict per ``run()`` parameter, with its
name, annotation, and default.
- ``has_configure`` (bool): whether the script defines ``configure()``.
- ``configure_schema`` (dict or ``None``): the literal dictionary
``configure()`` returns, when it can be read statically.
- ``docstring`` (str or ``None``): the script's top-level docstring.
- ``input_ports`` (list): ``{"name": str, "types": list[str]}`` dicts
derived from ``run()`` parameters; an unannotated parameter defaults
to ``["DataObject"]``.
Raises: FileNotFoundError: If script_path does not exist.
list_codeblock_backends — function
Stability: provisional · Since 0.3.1
list_codeblock_backends() -> 'tuple[CodeBlockBackend, ...]'
Return every currently registered interpreter backend.
The first call loads the built-in backends (Python, notebook, R/Quarto, shell, MATLAB/Octave) on demand, so the result always includes them.
Returns: A tuple of the registered backends, in registration order.
normalise_extension — function
Stability: provisional · Since 0.3.1
normalise_extension(extension: 'str') -> 'str'
Clean up a file extension into a consistent .lowercase form.
Trims whitespace, lowercases, and adds a leading dot if missing, so that
"CSV", " .csv ", and "csv" all become ".csv".
Args: extension: The raw extension, with or without a leading dot.
Returns:
The normalised extension, for example ".csv".
Raises: ValueError: If the extension is empty or contains a path separator.
Example: >>> normalise_extension("CSV") '.csv'
plan_input_filenames — function
Stability: provisional · Since 0.3.1
plan_input_filenames(objects: 'Sequence[DataObject]', *, extension: 'str') -> 'list[str]'
Pick a unique filename for each input object on one port.
Names each file after its source (when known) or a numbered item_NNNN
stem otherwise, all sharing the given extension, and de-duplicates so no two
objects collide.
Args: objects: The data objects to be written to one input port, in order. extension: File extension for the files (with or without a leading dot).
Returns: One filename per object, in the same order.
prepare_codeblock_exchange — function
Stability: provisional · Since 0.3.1
prepare_codeblock_exchange(inputs: 'Mapping[str, DataObject | Collection]', port_configs: 'Sequence[CodeBlockExchangePort]', *, exchange_root: 'Path', block_id: 'str', run_id: 'str', materialise_adapter: 'MaterialiseAdapter', block_slug: 'str' = 'codeblock') -> 'CodeBlockExchangeManifest'
Lay out the run's folders and write the declared inputs to files.
Creates the exchange folders, then, for each declared input port, writes its value(s) to files using materialise_adapter. A required input with no value records an error diagnostic; an optional one records a warning.
Args: inputs: Input values keyed by input-port name. port_configs: The declared input and output ports for the run. exchange_root: Root folder that holds all runs' exchange directories. block_id: Identifier of the block instance. run_id: Identifier of this run. materialise_adapter: Function that writes one data object to a file. block_slug: Short label prefixed to the block folder name.
Returns: The manifest after inputs are written, including any input diagnostics.
register_codeblock_backend — function
Stability: provisional · Since 0.3.1
register_codeblock_backend(backend: 'CodeBlockBackend', *, replace: 'bool' = False) -> 'None'
Add an interpreter backend to the in-process Code Block registry.
Use this to teach the Code Block a new language (for example a Julia or Go backend) without editing the Code Block itself. Once registered, the Code Block routes any script whose extension the backend declares to that backend. The notebook, R/Quarto, shell, and MATLAB-family backends register themselves through this same entry point.
Args:
backend: The backend to register. Its name must not be empty and
each of its extensions must start with a dot.
replace: When True, replace any existing backend that shares the
same name or any extension. When False (the default), a clash
raises instead of overwriting.
Raises:
ValueError: If the backend declares no name, declares no extensions,
declares an extension without a leading dot, or clashes with an
already-registered backend while replace is False.
resolve_codeblock_backend — function
Stability: provisional · Since 0.3.1
resolve_codeblock_backend(script_path: 'Path', config: 'CodeBlockConfig') -> 'CodeBlockBackend'
Pick the registered backend that can run a given script.
Args:
script_path: Path to the script whose extension selects the backend.
config: The Code Block configuration, passed to each backend's
CodeBlockBackend.supports check.
Returns: The first registered backend that reports it can run script_path.
Raises: ValueError: If no registered backend handles the script's extension.
resolve_codeblock_data_type — function
Stability: provisional · Since 0.3.1
resolve_codeblock_data_type(data_type: 'str') -> 'type[DataObject]'
Look up a core data-type name and return its class.
Args:
data_type: A core data-type name such as "DataFrame" or "Array".
Returns: The matching data-type class.
Raises: ValueError: If the name is not one of the core data types.
resolve_script_interpreter — function
Stability: provisional · Since 0.3.1
resolve_script_interpreter(script_path: 'Path', *, environment_config: 'Mapping[str, Any] | None' = None, project_dir: 'Path', mode: 'InterpreterMode' = 'auto', interpreter_path: 'Path | str | None' = None) -> 'ResolvedInterpreter'
Choose the Python interpreter command to run a .py script.
Confirms the script lives inside the project and ends in .py, picks a
Python executable (the current one, an explicit path, or a configured one),
and records the working directory, environment overrides, and interpreter
version.
Args:
script_path: Path to the script to run.
environment_config: Optional hints such as interpreter_path,
working_directory, and environment variables.
project_dir: Absolute path to the project root the script must stay in.
mode: "auto" to detect an interpreter, or "existing" to require
an explicit interpreter path.
interpreter_path: Explicit interpreter path; required when mode is
"existing".
Returns: The resolved interpreter command for the script.
Raises:
UnsupportedScriptExtensionError: If the script is not a .py file.
InterpreterResolutionError: If no usable interpreter can be resolved.
run_codeblock_process — function
Stability: provisional · Since 0.3.1
run_codeblock_process(*, argv: 'Sequence[str]', cwd: 'Path', env_delta: 'Mapping[str, str]', timeout_seconds: 'float | None') -> 'subprocess.CompletedProcess[str]'
Launch an interpreter as a subprocess and capture its output.
Backends call this to actually run a script. It starts from the current process environment, layers the backend's extra variables on top, captures standard output and standard error as text, and enforces an optional time limit.
Args:
argv: The full command to run, for example ["python", "script.py"].
cwd: Working directory to launch the process from.
env_delta: Extra environment variables to add on top of the current
environment.
timeout_seconds: Wall-clock limit in seconds, or None for no limit.
Returns: The completed process, with its exit code and captured text output. A non-zero exit code is returned rather than raised, so the caller decides how to react to a failing script.
Raises: CodeBlockTimeoutError: If the process runs longer than timeout_seconds.
safe_exchange_name — function
Stability: provisional · Since 0.3.1
safe_exchange_name(value: 'str', *, fallback: 'str' = 'port') -> 'str'
Turn a free-form name into a single safe folder/file name component.
Replaces characters that are not letters, digits, _, ., or -
with underscores and trims stray punctuation, so an arbitrary port name can
be used as a folder name.
Args: value: The name to sanitise. fallback: Name to use when value sanitises to nothing.
Returns: A path-safe name, or fallback if nothing usable remains.
Example: >>> safe_exchange_name("my port!") 'my_port'
selected_codeblock_capabilities — function
Stability: provisional · Since 0.3.1
selected_codeblock_capabilities(config: 'CodeBlockConfig') -> 'dict[str, str]'
List the save/load handler chosen for each port, where one is pinned.
Args: config: The Code Block configuration to inspect.
Returns:
A mapping from direction:port (for example "input:data") to the
pinned handler identifier, for ports that pin one.
unregister_codeblock_backend — function
Stability: provisional · Since 0.3.1
unregister_codeblock_backend(name: 'str') -> 'None'
Remove a previously registered backend by its name.
Args:
name: The backend's name. An unknown name is ignored.
utc_now_iso — function
Stability: provisional · Since 0.3.1
utc_now_iso() -> 'str'
Return the current UTC time as an ISO-8601 string with second precision.
Returns:
A timestamp such as "2026-06-28T12:00:00Z".
validate_codeblock_config — function
Stability: provisional · Since 0.3.1
validate_codeblock_config(config: 'Mapping[str, Any]', *, project_dir: 'Path', registry: 'BlockRegistry | None' = None) -> 'list[CodeBlockValidationDiagnostic]'
Check a saved Code Block configuration and return any problems found.
Runs the configuration through the same model the runtime uses, then checks the script path and folders stay inside the project, the script's extension has a backend to run it, and each declared port is well-formed. No interpreter is launched. When a registry is provided, it also checks that a save/load handler exists for each port.
Args: config: The raw saved configuration mapping. project_dir: Absolute path to the project root. registry: Optional block registry used to check that a file-format handler exists for each declared port.
Returns: A list of diagnostics; empty when the configuration is valid.