Hooks and plugins¶
Hooks let you add domain-specific behaviour to the catalog operation lifecycle without modifying ogcat core.
Hook protocols¶
Each hook is a plain Python class that implements one or more of the following methods. You only need to implement the methods you care about.
Method |
When it runs |
|---|---|
|
Before schema validation. Mutate |
|
After schema validation. Inspect the validation report. |
|
After the locator is proposed. Replace or extend |
|
During derived metadata collection. Return a dict to merge into |
|
Just before writing the record. Last chance to mutate metadata. |
|
Just after the record is written. Register side-effects here. |
|
Before committing the transaction. |
|
After committing the transaction (errors here become warnings). |
|
When the operation fails. |
|
After rollback has run. |
Registering hooks¶
Pass a plugin registry when creating or opening a catalog:
from ogcat import Catalog, CatalogSpec, PluginRegistry
from ogcat.hooks import OperationContext
class TitleFromFilenameHook:
"""Set title from the source filename when the caller did not supply one."""
def before_validate_metadata(self, context: OperationContext) -> None:
if context.source_path is not None:
context.user_metadata.setdefault("title", context.source_path.stem)
spec = CatalogSpec(catalog_name="files")
plugins = PluginRegistry([TitleFromFilenameHook()])
catalog = Catalog.create("./my-catalog", spec, plugins=plugins)
You can also register hooks after catalog creation:
catalog.hook_manager.register(TitleFromFilenameHook())
Metadata extractor hooks¶
Implement extract_metadata to add derived metadata:
class ChecksumHook:
"""Compute a SHA-256 checksum and store it in derived metadata."""
def extract_metadata(self, context: OperationContext) -> dict | None:
if context.source_path is None:
return None
import hashlib
digest = hashlib.sha256(context.source_path.read_bytes()).hexdigest()
return {"sha256": digest}
OperationContext¶
OperationContext is the mutable object passed to every hook. The most
commonly used fields are:
context.user_metadata— mutable before validationcontext.derived_metadata— mutable during extractioncontext.source_path— source path when availablecontext.planned_locators— list of locators to be resolvedcontext.operation_type— name of the current operation
Warnings¶
Hooks can record non-fatal warnings with context.add_warning():
context.add_warning("title was derived from filename", hook_name="TitleFromFilenameHook")
Warnings appear in after_commit errors and are attached to the operation
context. They do not prevent the record from being written.
A complete example¶
See the intermediate tutorial for a full worked example including a custom extractor hook and smoke tests.