Define and validate options¶
Set options_model to a Pydantic BaseModel subclass. This keeps the transport representation—CLI strings, JSON, or worker messages—outside the plugin's execution logic.
Reject misspelled fields¶
from pathlib import Path
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
class Options(BaseModel):
model_config = ConfigDict(extra="forbid")
output: Path
dialect: Literal["stable", "experimental"] = "stable"
workers: int = Field(default=1, ge=1)
Use Pydantic validators for shape, type, range, and relationships that can be checked without the resolved document. A host normally constructs this model before calling execute.
Use no options¶
from transpiler_mate.api import EmptyOptions, TranspilerContext, transpiler_plugin
@transpiler_plugin(
name="fixed-target",
description="Generate the fixed target format",
options_model=EmptyOptions,
)
def plugin(context: TranspilerContext, options: EmptyOptions) -> None:
...
EmptyOptions is not an invitation to accept arbitrary configuration: its extra="forbid" setting rejects every unknown field.
Separate option validation from domain validation¶
- Invalid types, missing option fields, forbidden extra fields, and numeric constraints should produce Pydantic
ValidationErrorwhile constructing the options model. - A well-formed option that cannot be honored for this particular CWL document should cause
PluginFailureErrorduring execution. - A valid option that fails because an external tool crashes should cause
PluginExecutionErrorduring execution.
For example, validate that workers >= 1 in the model. If dialect="stable" is valid in general but the current document uses an experimental CWL feature, raise PluginFailureError from execute.
Do not catch a ValidationError merely to relabel it as a plugin error unless the validation occurs inside execution and you can add meaningful domain context. Runtime behavior for top-level option validation is outside this API.