Source code for eve_resource.hooks
# -*- coding: utf-8 -*-
from typing import Any, Optional, Iterable
from eve import Eve
from .event import Event, request_event, mongo_event, EventFuncType
# from .exceptions import NotCallable
# from .utils import callable_or_error # , mongo_aliases, request_aliases
[docs]class EventHooks(object):
"""An :class:`Event` container that holds events for a domain resource.
:param resource: The domain resource
:param EventType: The :class:`Event` class or function for the events of
this class.
"""
def __init__(self, resource: str, EventType=Event) -> None:
self.EventType = EventType
self.resource = resource
self.events = []
def _make_and_append(self, event: str, func: EventFuncType) -> None:
"""Creates a new event and appends to events."""
self.events.append(
self.EventType(event, self.resource, func)
)
[docs] def event(self, event: Any, func: Optional[EventFuncType]=None
) -> Optional[EventFuncType]:
"""Add's an event to the instance.
:param event: A string or instance of :attr:`EventType`.
:param func: A callable to register, only used if ``event`` is a
string, that we use to create an instance of
:attr:`EventType`
"""
def inner(func: EventFuncType) -> EventFuncType:
self._make_and_append(event, func)
return func
if isinstance(event, str):
return inner if func is None else inner(func)
if isinstance(event, self.EventType):
if event.resource != self.resource:
raise ValueError('event resource does not match.')
return self.events.append(event)
raise TypeError('{} should be string or {}'.format(
event, self.EventType.__name__)
)
[docs] def multi_event(self, *events, func: Optional[EventFuncType]=None
) -> Optional[EventFuncType]:
"""Register's the same function for multiple events. Can be used as
a decorator.
:param events: Iterable of strings that are the api events to register
the function with.
:param func: The function to use for the api hook event.
"""
def inner(func: EventFuncType) -> EventFuncType:
for event in events:
self.event(event, func)
return func
return inner(func) if func is not None else inner
[docs] def init_api(self, api: Eve) -> None:
"""Register all event's with an :class:`eve.Eve` instance.
:param api: An :class:`eve.Eve` instance
:raises TypeError: If api is not an :class:`eve.Eve` instance
"""
if not isinstance(api, Eve):
raise TypeError(api)
for event in self:
event.register(api)
def __iter__(self) -> Iterable[Any]:
return iter(self.events)
def __repr__(self) -> str:
return "{n}('{r}', EventType={e})".format(
n=self.__class__.__name__,
r=self.resource,
e=self.EventType
)
def __call__(self, *events, func: Optional[EventFuncType]=None) -> Any:
"""Calls the appropriate :meth:`event` or :meth:`multi_event` with
the given parameters. Can be used as a decorator.
:param events: A single event string or multiple event strings.
If the lenght is 1, then we call :meth:`event` else
we call :meth:`multi_event`.
:param func: The function to add as the event.
"""
def inner(func: EventFuncType):
if len(events) == 1:
return self.event(events[0], func=func)
return self.multi_event(*events, func=func)
return inner(func) if func is not None else inner
[docs]def mongo_hooks(resource: str) -> EventHooks:
"""Returns a :class:`EventHooks` set-up for mongo events.
"""
return EventHooks(resource, mongo_event)
[docs]def request_hooks(resource: str) -> EventHooks:
"""Returns a :class:`EventHooks` set-up for request events.
"""
return EventHooks(resource, request_event)
[docs]class Hooks(object):
"""Container object that holds :class:`EventHooks` for mongo and
request events.
:param resource: The domain resource the hooks are for.
"""
def __init__(self, resource: str) -> None:
self.resource = resource
self._mongo = None
self._request = None
@property
def mongo(self) -> EventHooks:
"""A :class:`EventHooks` setup for mongo type events that can
be registered with an :class:`eve.Eve` api.
"""
if self._mongo is None:
self._mongo = mongo_hooks(self.resource)
return self._mongo
@property
def request(self) -> EventHooks:
"""A :class:`EventHooks` setup for request type events that can
be registered with an :class:`eve.Eve` api.
"""
if self._request is None:
self._request = request_hooks(self.resource)
return self._request
[docs] def init_api(self, api: Eve) -> None:
"""Register's the hooks with an :class:`eve.Eve` instance.
:param api: A :class:`eve.Eve`
:raises TypeError: If ``api`` is not an :class:`eve.Eve` instance
"""
if not isinstance(api, Eve):
raise TypeError(api)
self.mongo.init_api(api)
self.request.init_api(api)