exlab_wizard.plugins.base#
Plugin contract base class. Backend Spec §6.1.
Defines the public surface that every plugin author subclasses:
Plugin– the abstract contract: required methods (can_handle,transform), optional lifecycle hooks (pre_transform_all,post_transform_all,describe_changes,on_plugin_failure,validate_variables), and the class attributes the host’s registry cross-checks againstmanifest.yml(name,version,supported_extensions,api_version,required_variables,optional_variables).PluginContext– the frozen dataclass the host hands the plugin on every per-file call (variable map, destination root, answers file, run identity, dry-run flag, and the structured log shim).FileChange– the per-mutation report shape used byPlugin.describe_changes()for dry-run previews.PluginErrorandPluginInputRequired– re-exports of the canonical hierarchy fromexlab_wizard.errors. Plugin authors import the names from this module for convenience; the host catches them by their canonical class so the two views point at the same exception object.
Note (v0.7): the legacy transform_readme hook is intentionally omitted.
README mutation is post-plugin and non-pluggable – see Backend Spec §6.1.5
(“What plugins must not touch”) and §10.8.
Classes
|
A single mutation a plugin would make. |
|
Abstract base class for all ExLab-Wizard plugins. |
|
Read-only context handed to every plugin lifecycle hook. |
- class exlab_wizard.plugins.base.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.base.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.base.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.base.PluginError[source]#
Bases:
ExLabErrorRaised by plugin workers to signal expected failure. Backend Spec §6.