Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/events.py: 51%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Infrastructure for registering and firing callbacks on application events.
3Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
4be called at specific times, or a collection of alternative methods to try,
5callbacks are designed to be used by extension authors. A number of callbacks
6can be registered for the same event without needing to be aware of one another.
8The functions defined in this module are no-ops indicating the names of available
9events and the arguments which will be passed to them.
11.. note::
13 This API is experimental in IPython 2.0, and may be revised in future versions.
14"""
16from __future__ import annotations
18from typing import TYPE_CHECKING, Any, Callable, Iterable, TypeVar
20if TYPE_CHECKING:
21 from IPython.core.interactiveshell import (
22 ExecutionInfo,
23 ExecutionResult,
24 InteractiveShell,
25 )
28class EventManager:
29 """Manage a collection of events and a sequence of callbacks for each.
31 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
32 instances as an ``events`` attribute.
34 .. note::
36 This API is experimental in IPython 2.0, and may be revised in future versions.
37 """
39 def __init__(
40 self,
41 shell: InteractiveShell,
42 available_events: Iterable[str],
43 print_on_error: bool = True,
44 ) -> None:
45 """Initialise the :class:`CallbackManager`.
47 Parameters
48 ----------
49 shell
50 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
51 available_events
52 An iterable of names for callback events.
53 print_on_error:
54 A boolean flag to set whether the EventManager will print a warning which a event errors.
55 """
56 self.shell = shell
57 self.callbacks: dict[str, list[Callable[..., Any]]] = {
58 n: [] for n in available_events
59 }
60 self.print_on_error = print_on_error
62 def register(self, event: str, function: Callable[..., Any]) -> None:
63 """Register a new event callback.
65 Parameters
66 ----------
67 event : str
68 The event for which to register this callback.
69 function : callable
70 A function to be called on the given event. It should take the same
71 parameters as the appropriate callback prototype.
73 Raises
74 ------
75 TypeError
76 If ``function`` is not callable.
77 KeyError
78 If ``event`` is not one of the known events.
79 """
80 if not callable(function):
81 raise TypeError('Need a callable, got %r' % function)
82 if function not in self.callbacks[event]:
83 self.callbacks[event].append(function)
85 def unregister(self, event: str, function: Callable[..., Any]) -> None:
86 """Remove a callback from the given event."""
87 if function in self.callbacks[event]:
88 return self.callbacks[event].remove(function)
90 raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
92 def trigger(self, event: str, *args: Any, **kwargs: Any) -> None:
93 """Call callbacks for ``event``.
95 Any additional arguments are passed to all callbacks registered for this
96 event. Exceptions raised by callbacks are caught, and a message printed.
97 """
98 for func in self.callbacks[event][:]:
99 try:
100 func(*args, **kwargs)
101 except (Exception, KeyboardInterrupt):
102 if self.print_on_error:
103 print(
104 "Error in callback {} (for {}), with arguments args {},kwargs {}:".format(
105 func, event, args, kwargs
106 )
107 )
108 self.shell.showtraceback()
110# event_name -> prototype mapping
111available_events: dict[str, Callable[..., Any]] = {}
113_CallbackT = TypeVar("_CallbackT", bound=Callable[..., Any])
115def _define_event(callback_function: _CallbackT) -> _CallbackT:
116 """Decorator to register a function as an available event prototype."""
117 available_events[callback_function.__name__] = callback_function
118 return callback_function
120# ------------------------------------------------------------------------------
121# Callback prototypes
122#
123# No-op functions which describe the names of available events and the
124# signatures of callbacks for those events.
125# ------------------------------------------------------------------------------
127@_define_event
128def pre_execute() -> None:
129 """Fires before code is executed in response to user/frontend action.
131 This includes comm and widget messages and silent execution, as well as user
132 code cells.
133 """
134 pass
136@_define_event
137def pre_run_cell(info: ExecutionInfo) -> None:
138 """Fires before user-entered code runs.
140 Parameters
141 ----------
142 info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
143 An object containing information used for the code execution.
144 """
145 pass
147@_define_event
148def post_execute() -> None:
149 """Fires after code is executed in response to user/frontend action.
151 This includes comm and widget messages and silent execution, as well as user
152 code cells.
153 """
154 pass
156@_define_event
157def post_run_cell(result: ExecutionResult) -> None:
158 """Fires after user-entered code runs.
160 Parameters
161 ----------
162 result : :class:`~IPython.core.interactiveshell.ExecutionResult`
163 The object which will be returned as the execution result.
164 """
165 pass
167@_define_event
168def shell_initialized(ip: InteractiveShell) -> None:
169 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
171 This is before extensions and startup scripts are loaded, so it can only be
172 set by subclassing.
174 Parameters
175 ----------
176 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
177 The newly initialised shell.
178 """
179 pass