Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/events.py: 52%
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, TypeVar
19from collections.abc import Callable, Iterable
21if TYPE_CHECKING:
22 from IPython.core.interactiveshell import (
23 ExecutionInfo,
24 ExecutionResult,
25 InteractiveShell,
26 )
29class EventManager:
30 """Manage a collection of events and a sequence of callbacks for each.
32 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
33 instances as an ``events`` attribute.
35 .. note::
37 This API is experimental in IPython 2.0, and may be revised in future versions.
38 """
40 def __init__(
41 self,
42 shell: InteractiveShell,
43 available_events: Iterable[str],
44 print_on_error: bool = True,
45 ) -> None:
46 """Initialise the :class:`CallbackManager`.
48 Parameters
49 ----------
50 shell
51 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
52 available_events
53 An iterable of names for callback events.
54 print_on_error:
55 A boolean flag to set whether the EventManager will print a warning which a event errors.
56 """
57 self.shell = shell
58 self.callbacks: dict[str, list[Callable[..., Any]]] = {
59 n: [] for n in available_events
60 }
61 self.print_on_error = print_on_error
63 def register(self, event: str, function: Callable[..., Any]) -> None:
64 """Register a new event callback.
66 Parameters
67 ----------
68 event : str
69 The event for which to register this callback.
70 function : callable
71 A function to be called on the given event. It should take the same
72 parameters as the appropriate callback prototype.
74 Raises
75 ------
76 TypeError
77 If ``function`` is not callable.
78 KeyError
79 If ``event`` is not one of the known events.
80 """
81 if not callable(function):
82 raise TypeError('Need a callable, got %r' % function)
83 if function not in self.callbacks[event]:
84 self.callbacks[event].append(function)
86 def unregister(self, event: str, function: Callable[..., Any]) -> None:
87 """Remove a callback from the given event."""
88 if function in self.callbacks[event]:
89 return self.callbacks[event].remove(function)
91 raise ValueError(f'Function {function!r} is not registered as a {event} callback')
93 def trigger(self, event: str, *args: Any, **kwargs: Any) -> None:
94 """Call callbacks for ``event``.
96 Any additional arguments are passed to all callbacks registered for this
97 event. Exceptions raised by callbacks are caught, and a message printed.
98 """
99 for func in self.callbacks[event][:]:
100 try:
101 func(*args, **kwargs)
102 except (Exception, KeyboardInterrupt):
103 if self.print_on_error:
104 print(
105 "Error in callback {} (for {}), with arguments args {},kwargs {}:".format(
106 func, event, args, kwargs
107 )
108 )
109 self.shell.showtraceback()
111# event_name -> prototype mapping
112available_events: dict[str, Callable[..., Any]] = {}
114_CallbackT = TypeVar("_CallbackT", bound=Callable[..., Any])
116def _define_event(callback_function: _CallbackT) -> _CallbackT:
117 """Decorator to register a function as an available event prototype."""
118 available_events[callback_function.__name__] = callback_function
119 return callback_function
121# ------------------------------------------------------------------------------
122# Callback prototypes
123#
124# No-op functions which describe the names of available events and the
125# signatures of callbacks for those events.
126# ------------------------------------------------------------------------------
128@_define_event
129def pre_execute() -> None:
130 """Fires before code is executed in response to user/frontend action.
132 This includes comm and widget messages and silent execution, as well as user
133 code cells.
134 """
135 pass
137@_define_event
138def pre_run_cell(info: ExecutionInfo) -> None:
139 """Fires before user-entered code runs.
141 Parameters
142 ----------
143 info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
144 An object containing information used for the code execution.
145 """
146 pass
148@_define_event
149def post_execute() -> None:
150 """Fires after code is executed in response to user/frontend action.
152 This includes comm and widget messages and silent execution, as well as user
153 code cells.
154 """
155 pass
157@_define_event
158def post_run_cell(result: ExecutionResult) -> None:
159 """Fires after user-entered code runs.
161 Parameters
162 ----------
163 result : :class:`~IPython.core.interactiveshell.ExecutionResult`
164 The object which will be returned as the execution result.
165 """
166 pass
168@_define_event
169def shell_initialized(ip: InteractiveShell) -> None:
170 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
172 This is before extensions and startup scripts are loaded, so it can only be
173 set by subclassing.
175 Parameters
176 ----------
177 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
178 The newly initialised shell.
179 """
180 pass