Extensions (erlab.extensions)

Simple analysis and loader extensions for ERLab.

Extension authors normally need only routine() or loader(). Decorated functions remain ordinary Python functions and work directly in notebooks.

exception erlab.extensions.ExtensionError[source]

Bases: RuntimeError

Base class for errors raised by the ERLab extension API.

Catch this error when one handler must process import, validation, lookup, and execution failures in the same way.

exception erlab.extensions.ExtensionExecutionError[source]

Bases: ExtensionError

An extension call failed or returned an unsupported value.

exception erlab.extensions.ExtensionImportError[source]

Bases: ExtensionError

An extension source could not be read, verified, or imported.

exception erlab.extensions.ExtensionNotFoundError[source]

Bases: ExtensionError

A requested extension source or capability is not available.

exception erlab.extensions.ExtensionSignatureError[source]

Bases: ExtensionError

A decorated function has an unsupported signature or annotation.

class erlab.extensions.LoadedScript(erlab)[source]

Bases: object

Imported extension script with natural access to its public functions.

Instances are returned by erlab.extensions.load_script(). Call a decorated function as a normal attribute. Use erlab only when you need descriptors, the source hash, or other import information.

Parameters:

erlab (LoadedScriptInfo) – ERLab information for the imported script.

Examples

>>> from erlab.extensions import load_script
>>> extension = load_script("my_extension.py")
>>> result = extension.normalize(data)
>>> tuple(extension.erlab.routines)
('normalize',)
__getattr__(name)[source]

Return a decorated function or another public script attribute.

property erlab: LoadedScriptInfo

Return descriptors and import information owned by ERLab.

class erlab.extensions.LoadedScriptInfo(*, path, source_hash, module, routines, loaders)[source]

Bases: object

ERLab information for one loaded extension script.

Access this object through LoadedScript.erlab. Keeping ERLab-owned attributes in one namespace lets extension functions use ordinary names such as path, module, or loaders.

Parameters:
property capabilities: tuple[RoutineDescriptor | LoaderDescriptor, ...]

Return all validated capabilities in source definition order.

Returns:

tuple of RoutineDescriptor or LoaderDescriptor – The routines followed by the loaders from the imported script.

class erlab.extensions.LoaderDescriptor(**data)[source]

Bases: BaseModel

Public description of a path-based data loader.

Parameters:
  • id (str) – Stable capability identifier.

  • name (str) – Display name.

  • category (str) – Display category.

  • summary (str) – Short description.

  • function_name (str) – Python function name in the source module.

  • parameters (tuple[ParameterDescriptor, ...]) – Parameters shown after the input path.

  • extensions (tuple[str, ...]) – Optional filename extensions, including the leading dot.

  • extension_api_version (Literal[1]) – Extension protocol version used by this descriptor.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
name: str
category: str
summary: str
function_name: str
parameters: tuple[ParameterDescriptor, ...]
extensions: tuple[str, ...]
extension_api_version: typing.Literal[1]
class erlab.extensions.ParameterDescriptor(**data)[source]

Bases: BaseModel

Description of one user-editable extension parameter.

Parameters:
  • id (str) – Python parameter name.

  • kind (ParameterKind) – Editor type used by graphical clients.

  • required (bool) – Whether the caller must supply a value.

  • optional (bool) – Whether None is an accepted value.

  • default (bool | int | float | str | None) – JSON-compatible default value, if one exists.

  • choices (tuple[bool | int | float | str, ...]) – Accepted values for a literal or enumeration parameter.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
kind: ParameterKind
required: bool
optional: bool
default: bool | int | float | str | None
choices: tuple[bool | int | float | str, ...]
class erlab.extensions.ParameterKind(*values)[source]

Bases: StrEnum

Supported editor type for an extension parameter.

Variables:
  • BOOLEAN – A Boolean value.

  • INTEGER – An integer value.

  • NUMBER – A floating-point value.

  • STRING – A text value.

  • PATH – A file-system path.

  • LITERAL – One value from a Literal annotation.

  • ENUM – One value from an enumeration.

BOOLEAN = 'boolean'
INTEGER = 'integer'
NUMBER = 'number'
STRING = 'string'
PATH = 'path'
LITERAL = 'literal'
ENUM = 'enum'
class erlab.extensions.RoutineDescriptor(**data)[source]

Bases: BaseModel

Public description of a single-input analysis routine.

Parameters:
  • id (str) – Stable capability identifier.

  • name (str) – Display name.

  • category (str) – Display category.

  • summary (str) – Short user-facing description.

  • function_name (str) – Python function name in the source module.

  • parameters (tuple[ParameterDescriptor, ...]) – Parameters shown after the input array.

  • extension_api_version (Literal[1]) – Extension protocol version used by this descriptor.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
name: str
category: str
summary: str
function_name: str
parameters: tuple[ParameterDescriptor, ...]
extension_api_version: typing.Literal[1]
erlab.extensions.load_script(path, *, module_name=None, expected_source_hash=None)[source]

Import and validate all decorated capabilities in a Python script.

The source directory is not added to sys.path. Each call uses a new module name unless module_name is supplied.

Parameters:
  • path (PathLike[str] | str) – Python source file.

  • module_name (str | None, default: None) – Import name. The name must not already exist in sys.modules. Graphical clients use a name that identifies their session.

  • expected_source_hash (str | None, default: None) – Required SHA-256 source hash. A mismatch stops the import.

Returns:

LoadedScript – Imported module, source hash, and validated capabilities.

Raises:
Return type:

LoadedScript

Examples

A script can contain routines, loaders, or both.

>>> from erlab.extensions import load_script
>>> loaded = load_script("my_lab_extension.py")
>>> tuple(loaded.erlab.routines)
('normalize',)
erlab.extensions.loader(*, name=None, id=None, category='Other', summary='', extensions=())[source]

Mark a normal Python function as an external data loader.

The first parameter must accept pathlib.Path. The result must be an xarray DataArray, Dataset, or DataTree.

Parameters:
  • name (str | None, default: None) – Display name. The function name is used by default.

  • id (str | None, default: None) – Stable capability identifier.

  • category (str, default: 'Other') – Group shown in graphical clients.

  • summary (str, default: '') – Short user-facing description.

  • extensions (str | Iterable[str], default: ()) – One filename extension or an iterable of extensions accepted by the loader. The leading dot is optional.

Returns:

callable – A decorator that returns the supplied function unchanged.

Return type:

Callable[[Callable[[…], Any]], Callable[[…], Any]]

Examples

>>> from pathlib import Path
>>> import xarray as xr
>>> from erlab.extensions import loader
>>> @loader(name="Text values", extensions=(".txt",))
... def load_text(path: Path) -> xr.DataArray:
...     return xr.DataArray([float(path.read_text())])
erlab.extensions.routine(*, name=None, id=None, category='Other', summary='')[source]

Mark a normal Python function as an ImageTool analysis routine.

The decorator does not wrap the function. Calling the decorated function in a notebook has the same behavior as calling the original function.

Parameters:
  • name (str | None, default: None) – Display name. The function name is used by default.

  • id (str | None, default: None) – Stable capability identifier. Set this value before renaming a function.

  • category (str, default: 'Other') – Group shown in graphical clients.

  • summary (str, default: '') – Short user-facing description.

Returns:

callable – A decorator that returns the supplied function unchanged.

Return type:

Callable[[Callable[[…], DataArray]], Callable[[…], DataArray]]

Examples

>>> import xarray as xr
>>> from erlab.extensions import routine
>>> @routine(name="Double")
... def double(data: xr.DataArray) -> xr.DataArray:
...     return 2 * data
>>> double(xr.DataArray([1, 2])).values.tolist()
[2, 4]
erlab.extensions.run_loader(path, *, loader_id, script=None, registered_script=None, source_hash=None, parameters=None)[source]

Run one decorated loader without manager or Qt knowledge.

Parameters:
  • path (PathLike[str] | str) – Input file path.

  • loader_id (str) – Capability identifier.

  • script (PathLike[str] | str | None, default: None) – Direct Python source path.

  • registered_script (str | None, default: None) – Registered Python script filename.

  • source_hash (str | None, default: None) – Required source SHA-256 hash for catalog-based replay. You can also use it to verify a direct script.

  • parameters (Mapping[str, Any] | None, default: None) – Loader parameter values.

Returns:

xarray.DataArray, xarray.Dataset, or xarray.DataTree – Validated loader output.

Raises:
Return type:

DataArray | Dataset | DataTree

Examples

>>> from erlab.extensions import run_loader
>>> data = run_loader(
...     "scan.txt",
...     script="my_lab_extension.py",
...     loader_id="load_scan",
... )
erlab.extensions.run_routine(data, *, routine_id, script=None, registered_script=None, source_hash=None, parameters=None)[source]

Run one decorated routine without manager or Qt knowledge.

Supply script for a direct notebook call. Manager replay can instead supply registered_script and source_hash so the active catalog resolves the recorded source.

Parameters:
  • data (DataArray) – Input array.

  • routine_id (str) – Capability identifier.

  • script (PathLike[str] | str | None, default: None) – Python source file. This is optional when a manager catalog resolver exists.

  • registered_script (str | None, default: None) – Registered Python script filename.

  • source_hash (str | None, default: None) – Required source SHA-256 hash for catalog-based replay. You can also use it to verify a direct script.

  • parameters (Mapping[str, Any] | None, default: None) – User parameter values.

Returns:

xarray.DataArray – Validated routine result.

Raises:
Return type:

DataArray

Examples

>>> import xarray as xr
>>> from erlab.extensions import run_routine
>>> data = xr.DataArray([1.0, 2.0])
>>> result = run_routine(
...     data,
...     script="my_lab_extension.py",
...     routine_id="normalize",
... )