51
loading...
This website collects cookies to deliver better user experience
hook_impl
, making a class with a function that represents one of the hooks,from framework import hook_impl
class LowerHook:
@hook_impl
def start(pluggy_example):
pluggy_example.message = pluggy_example.message.lower()
pip install pluggy
import pluggy
# These don't need to match
HOOK_NAMESPACE = "pluggy_example" PROJECT_NAME = "pluggy_example"
hook_spec = pluggy.HookspecMarker(HOOK_NAMESPACE) hook_impl = pluggy.HookimplMarker(HOOK_NAMESPACE)
class PluggyExampleSpecs:
"""
This is where we spec out our frameworks hooks, I like to refer to them as
the lifecycle. Each of these functions is a hook that we are exposing to
our users, with the kwargs that we expect to pass them.
"""
@hook_spec
def start(self, pluggy_example: 'PluggyExample') -> None:
"""
The first hook that runs.
"""
pass
@hook_spec
def stop(self, pluggy_example: 'PluggyExample') -> None:
"""
The last hook that runs.
"""
pass
class PluggyExample:
"""
This may not need to be a class, but I wanted a container where all the
hooks had access to the message. This made sense to me to do as a class.
"""
def __init__(self, message="", hooks=None) -> None:
"""
Setup the plugin manager and register all the hooks.
"""
self._pm = pluggy.PluginManager(PROJECT_NAME)
self._pm.add_hookspecs(PluggyExampleSpecs)
self.message = message
self.hooks = hooks
if hooks:
self._register_hooks()
def _register_hooks(self) -> None:
for hook in self.hooks:
self._pm.register(hook)
def run(self):
"""
Run the hooks in the documented order, and pass in any kwargs the hook
needs access to. Here I am storing the message within this same class.
"""
self._pm.hook.start(pluggy_example=self)
self._pm.hook.stop(pluggy_example=self)
return self.message
class DefaultHook:
"""
These are some hooks that run by default, maybe these are created by the
framework author.
"""
@hook_impl
def start(pluggy_example):
pluggy_example.message = pluggy_example.message.upper()
@hook_impl
def stop(pluggy_example):
print(pluggy_example.message)
if __name__ == "__main__":
"""
The user of this framework can apply the hook in their own code without
changing the behavior of the framework, but the library has
implemented it's own default hooks.
"""
pe = PluggyExample(
message="hello world",
hooks=[
DefaultHook,
],
)
pe.run()
class LowerHook:
"""
This is a new hook that a plugin author has created to modify the behavior
of the framework to lowercase the message.
"""
@hook_impl
def start(pluggy_example):
pluggy_example.message = pluggy_example.message.lower()
from pluggy_example import PluggyExample pe = PluggyExample(
message="hello world",
hooks=[
DefaultHook,
LowerHook
],
)
pe.run()