Source code for napari_plugin_engine.markers

"""Hook annotation decorators"""
from typing import Callable, Optional

from .implementation import HookImplementation, HookSpecification


[docs]class HookSpecificationMarker: """Decorator helper class for marking functions as hook specifications. You can instantiate it with a project_name to get a decorator. Calling :py:meth:`.PluginManager.add_hookspecs` later will discover all marked functions if the :py:class:`.PluginManager` uses the same project_name. """ def __init__(self, project_name): self.project_name = project_name
[docs] def __call__( self, function: Optional[Callable] = None, firstresult: bool = False, historic: bool = False, warn_on_impl=None, ): """if passed a function, directly sets attributes on the function which will make it discoverable to :py:meth:`.PluginManager.add_hookspecs`. If passed no function, returns a decorator which can be applied to a function later using the attributes supplied. If ``firstresult`` is ``True`` the 1:N hook call (N being the number of registered hook implementation functions) will stop at I<=N when the I'th function returns a non-``None`` result. If ``historic`` is ``True`` calls to a hook will be memorized and replayed on later registered plugins. """ def setattr_hookspec_opts(func): if historic and firstresult: raise ValueError("cannot have a historic firstresult hook") setattr( func, HookSpecification.format_tag(self.project_name), dict( firstresult=firstresult, historic=historic, warn_on_impl=warn_on_impl, ), ) return func if function is not None: return setattr_hookspec_opts(function) else: return setattr_hookspec_opts
[docs]class HookImplementationMarker: """Decorator helper class for marking functions as hook implementations. You can instantiate with a ``project_name`` to get a decorator. Calling :meth:`.PluginManager.register` later will discover all marked functions if the :class:`.PluginManager` uses the same project_name. Parameters ---------- project_name : str A namespace for plugin implementations. Implementations decorated with this class will be discovered by ``PluginManager.register`` if and only if ``project_name`` matches the ``project_name`` of the ``PluginManager``. """ def __init__(self, project_name: str): self.project_name = project_name
[docs] def __call__( self, function: Optional[Callable] = None, *, hookwrapper: bool = False, optionalhook: bool = False, tryfirst: bool = False, trylast: bool = False, specname: str = '', ) -> Callable: """Call the marker instance. If passed a function, directly sets attributes on the function which will make it discoverable to :meth:`.PluginManager.register`. If passed no function, returns a decorator which can be applied to a function later using the attributes supplied. Parameters ---------- function : callable, optional A function to decorate as a hook implementation, If ``function`` is None, this method returns a function that can be used to decorate other functions. hookwrapper : bool, optional Whether this hook implementation behaves as a hookwrapper. by default False optionalhook : bool, optional If ``True``, a missing matching hook specification will not result in an error (by default it is an error if no matching spec is found), by default False. tryfirst : bool, optional If ``True`` this hook implementation will run as early as possible in the chain of N hook implementations for a specification, by default False trylast : bool, optional If ``True`` this hook implementation will run as late as possible in the chain of N hook implementations, by default False specname : str, optional If provided, ``specname`` will be used instead of the function name when matching this hook implementation to a hook specification during registration, by default the implementation function name must match the name of the corresponding hook specification. Returns ------- Callable If ``function`` is not ``None``, will decorate the function with attributes, and return the function. If ``function`` is None, will return a decorator that can be used to decorate functions. """ def set_hook_implementation_attributes(func): setattr( func, HookImplementation.format_tag(self.project_name), dict( hookwrapper=hookwrapper, optionalhook=optionalhook, tryfirst=tryfirst, trylast=trylast, specname=specname, ), ) return func if function is None: return set_hook_implementation_attributes else: return set_hook_implementation_attributes(function)