Ordering¶
By default implementations run in registration order. Two markers override that without touching registration:
@extension(tryfirst=True)runs earlier;@extension(trylast=True)runs later.
class WashPlugin:
@extension(tryfirst=True)
def prep_step(self, steps: list[str]) -> None:
steps.append("wash produce")
class GarnishPlugin:
@extension(trylast=True)
def prep_step(self, steps: list[str]) -> None:
steps.append("add garnish")
The exact rule¶
Implementations are grouped into three buckets and called in this order:
tryfirst,- normal,
trylast.
Within each bucket, order is registration order (first registered runs first). The demo registers the plugins out of order on purpose to prove the markers, not registration, decide the outcome.
Difference from pluggy
pluggy orders within a bucket last-registered-first (LIFO). pluginkit uses
first-registered-first (FIFO) because it is easier to reason about in a
teaching implementation. Both honour tryfirst/trylast the same way; only
the tie-break within a bucket differs. See
Differences from pluggy.
optional¶
A plugin may implement a hook the host never declared. Normally that is an error
(it usually means a typo), but optional=True makes it tolerated - useful
when one plugin targets several host versions:
class GarnishPlugin:
@extension(optional=True)
def not_a_real_hook(self) -> None:
"""Ignored cleanly if the host never specified this hook."""