exlab_wizard.plugins#
Plugins package. Backend Spec §6.
Re-exports the public plugin contract surface so plugin authors can write
from exlab_wizard.plugins import Plugin, PluginContext, FileChange,
PluginError, PluginInputRequired without reaching into private modules.
The host- and worker-side machinery (host, _worker, logger)
remains namespaced under the package and is not part of the plugin-author
public API.
- class exlab_wizard.plugins.FileChange(path, kind, summary, detail=<factory>)[source]#
Bases:
objectA single mutation a plugin would make. Used by
describe_changes.Backend Spec §6.1.3.
- path#
Absolute path under the rendered destination directory.
- kind#
One of
"modify","create","rename","delete".
- summary#
One-line human-readable description for UI display.
- detail#
Optional structured payload for richer dry-run previews (e.g.
{"writes": [{"cell": "B7", "value": "asmith"}]}).
- class exlab_wizard.plugins.HostPluginLogger(name='exlab_wizard.plugins')[source]#
Bases:
PluginLoggerIn-process forwarder used when plugins run without subprocess isolation.
Used by the host’s unit-test shim, by
--no-isolationdebug invocations of the plugin CLI (Backend Spec §6.10), and by the host when re-emitting parsed worker frames. Routes throughexlab_wizard.logging.get_logger()so records flow into the canonical handler chain (per-equipment file, central rotating, stderr).- Parameters:
name (
str)
- class exlab_wizard.plugins.Plugin[source]#
Bases:
ABCAbstract base class for all ExLab-Wizard plugins.
Backend Spec §6.1.3.
Lifecycle (one instance per creation session, all in the worker subprocess):
__init__()– cheap construction; no I/O.validate_variables(variables)– called once at registration in a short-lived validation worker.pre_transform_all(ctx)– called once before the file loop.For each matched file:
can_handle(file, variables)– cheap predicate.describe_changes(file, ctx)– only invoked in dry-run mode.transform(file, ctx)– the actual mutation.
post_transform_all(ctx)– called once after the file loop.on_plugin_failure(exc, ctx)– called only if any other hook raised.
- abstractmethod can_handle(file_path, variables)[source]#
Secondary filter, called after the extension match.
Cheap and side-effect-free. Returning
Falsemeans this file is skipped for this plugin only – other plugins still get a chance.
- describe_changes(file_path, ctx)[source]#
Return the dry-run preview for what
transformwould do.Default returns a single
"modify"FileChangewith no detail; plugins should override when the user-facing preview matters (e.g. listing the cells that would be written).- Parameters:
file_path (
Path)ctx (
PluginContext)
- Return type:
- on_plugin_failure(exc, ctx)[source]#
Called if any prior hook raised. Default: no-op.
Use to roll back partial state (delete a half-written sidecar file, restore a backup, close a leaked handle). The exception that caused the failure is passed in; the plugin MUST NOT re-raise. Returning normally means cleanup succeeded; raising means the cleanup itself failed and will be logged separately.
- Parameters:
exc (
Exception)ctx (
PluginContext)
- Return type:
- post_transform_all(ctx)[source]#
Called once after the file loop. Default: no-op.
Symmetric to
pre_transform_all()– close handles, flush buffers, etc. Not called ifpre_transform_allitself raised.- Parameters:
ctx (
PluginContext)- Return type:
- pre_transform_all(ctx)[source]#
Called once before the file loop. Default: no-op.
Use for batch setup that should be paid once per session (e.g. opening a workbook, opening a DB connection). State stored on
selfis preserved through the loop because the worker holds one instance for the whole session.- Parameters:
ctx (
PluginContext)- Return type:
- abstractmethod transform(file_path, ctx)[source]#
Mutate
file_pathin place.On unrecoverable failure raise
PluginErrorwith a human-readable message. On a discovered need for additional input, raisePluginInputRequired. Return value is ignored.- Parameters:
file_path (
Path)ctx (
PluginContext)
- Return type:
- validate_variables(variables)[source]#
Return a list of error strings; empty list means “valid”.
Default implementation reports any of
self.required_variablesthat are missing fromvariablesor are present but empty. Plugin authors override only to add bespoke checks (date-format, equipment-allowlist, etc.); the override should callsuper()first to preserve the missing-required check.Backend Spec §6.1.3 (variable validation in worker, not host).
- class exlab_wizard.plugins.PluginContext(variables, dst_root, answers_file, template_name, template_version, run_kind, equipment_id, project, dry_run, log)[source]#
Bases:
objectRead-only context handed to every plugin lifecycle hook.
Constructed once per creation session by the host and passed in across the IPC boundary. Plugins read from it but MUST NOT mutate it (the dataclass is frozen as a defensive measure – mutation attempts raise
dataclasses.FrozenInstanceError).Backend Spec §6.1.4.
- Parameters:
- log: PluginLogger#
- exception exlab_wizard.plugins.PluginError[source]#
Bases:
ExLabErrorRaised by plugin workers to signal expected failure. Backend Spec §6.
- exception exlab_wizard.plugins.PluginInputRequired(fields, reason)[source]#
Bases:
ExLabErrorRaised by plugin workers to escalate for additional input. Backend Spec §6.4.
- class exlab_wizard.plugins.PluginLogFrame(level: str, message: str, context: dict[str, ~typing.Any]=<factory>)[source]#
Bases:
StructWire format for worker-side log records.
The worker subprocess emits one
PluginLogFrame-shaped JSON object per log line on its stderr stream; the host parses each line and forwards into the canonical logger chain. Backend Spec §6.3.2.
- class exlab_wizard.plugins.PluginLogger[source]#
Bases:
ABCAbstract structured-log interface plugins receive on
ctx.log.Implementations forward to either the in-process stdlib logger (
HostPluginLogger) or the worker stderr channel (WorkerPluginLogger). Both expose the same four-method shape; plugin authors should not reach behind it.
- class exlab_wizard.plugins.WorkerPluginLogger(stream=None)[source]#
Bases:
PluginLoggerWorker-side forwarder. Emits JSON frames on stderr.
Used inside the plugin worker subprocess (Backend Spec §6.3.1). Each call serializes a
PluginLogFrameviamsgspec.jsonand writes a single newline-terminated line to the configured stream (defaults tosys.stderr). The host reads these line-by-line and forwards them to the canonical logger.The worker MUST NOT use stdout for log output – that channel is reserved for the IPC envelope. Stderr is the structured-log sideband.
Modules