diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-03-09 10:46:41 +0300 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-04-16 08:06:36 +0300 |
commit | 06f86b06399937bb2018841b5dd5fcbf4e54d7a0 (patch) | |
tree | cd0425510bb037c443f3b9d567ab3eb2a1f25a29 /sphinx/events.py | |
parent | 419f2e5fc904ec0819177305270ae1c5c8a38813 (diff) |
Make EventManager portable
So far, we need to bypass application object for modules to emit
a event. This make EventManager portable and easy to pass event
emitter. This brings modules less coupled with application object.
Diffstat (limited to 'sphinx/events.py')
-rw-r--r-- | sphinx/events.py | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/sphinx/events.py b/sphinx/events.py index 25a378d7c..334b4e053 100644 --- a/sphinx/events.py +++ b/sphinx/events.py @@ -14,10 +14,14 @@ from collections import OrderedDict, defaultdict from sphinx.errors import ExtensionError from sphinx.locale import __ +from sphinx.util import logging if False: # For type annotation from typing import Any, Callable, Dict, List # NOQA + from sphinx.application import Sphinx # NOQA + +logger = logging.getLogger(__name__) # List of all known core events. Maps name to arguments description. @@ -42,20 +46,25 @@ core_events = { class EventManager: - def __init__(self): - # type: () -> None + """Event manager for Sphinx.""" + + def __init__(self, app): + # type: (Sphinx) -> None + self.app = app self.events = core_events.copy() self.listeners = defaultdict(OrderedDict) # type: Dict[str, Dict[int, Callable]] self.next_listener_id = 0 def add(self, name): # type: (str) -> None + """Register a custom Sphinx event.""" if name in self.events: raise ExtensionError(__('Event %r already present') % name) self.events[name] = '' def connect(self, name, callback): # type: (str, Callable) -> int + """Connect a handler to specific event.""" if name not in self.events: raise ExtensionError(__('Unknown event name: %s') % name) @@ -66,18 +75,31 @@ class EventManager: def disconnect(self, listener_id): # type: (int) -> None + """Disconnect a handler.""" for event in self.listeners.values(): event.pop(listener_id, None) def emit(self, name, *args): # type: (str, Any) -> List + """Emit a Sphinx event.""" + try: + logger.debug('[app] emitting event: %r%s', name, repr(args)[:100]) + except Exception: + # not every object likes to be repr()'d (think + # random stuff coming via autodoc) + pass + results = [] for callback in self.listeners[name].values(): - results.append(callback(*args)) + results.append(callback(self.app, *args)) return results def emit_firstresult(self, name, *args): # type: (str, Any) -> Any + """Emit a Sphinx event and returns first result. + + This returns the result of the first handler that doesn't return ``None``. + """ for result in self.emit(name, *args): if result is not None: return result |