Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/IPython/core/events.py: 42%
50 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:05 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:05 +0000
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 backcall import callback_prototype
19class EventManager(object):
20 """Manage a collection of events and a sequence of callbacks for each.
22 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
23 instances as an ``events`` attribute.
25 .. note::
27 This API is experimental in IPython 2.0, and may be revised in future versions.
28 """
30 def __init__(self, shell, available_events, print_on_error=True):
31 """Initialise the :class:`CallbackManager`.
33 Parameters
34 ----------
35 shell
36 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
37 available_events
38 An iterable of names for callback events.
39 print_on_error:
40 A boolean flag to set whether the EventManager will print a warning which a event errors.
41 """
42 self.shell = shell
43 self.callbacks = {n:[] for n in available_events}
44 self.print_on_error = print_on_error
46 def register(self, event, function):
47 """Register a new event callback.
49 Parameters
50 ----------
51 event : str
52 The event for which to register this callback.
53 function : callable
54 A function to be called on the given event. It should take the same
55 parameters as the appropriate callback prototype.
57 Raises
58 ------
59 TypeError
60 If ``function`` is not callable.
61 KeyError
62 If ``event`` is not one of the known events.
63 """
64 if not callable(function):
65 raise TypeError('Need a callable, got %r' % function)
66 callback_proto = available_events.get(event)
67 if function not in self.callbacks[event]:
68 self.callbacks[event].append(callback_proto.adapt(function))
70 def unregister(self, event, function):
71 """Remove a callback from the given event."""
72 if function in self.callbacks[event]:
73 return self.callbacks[event].remove(function)
75 # Remove callback in case ``function`` was adapted by `backcall`.
76 for callback in self.callbacks[event]:
77 try:
78 if callback.__wrapped__ is function:
79 return self.callbacks[event].remove(callback)
80 except AttributeError:
81 pass
83 raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
85 def trigger(self, event, *args, **kwargs):
86 """Call callbacks for ``event``.
88 Any additional arguments are passed to all callbacks registered for this
89 event. Exceptions raised by callbacks are caught, and a message printed.
90 """
91 for func in self.callbacks[event][:]:
92 try:
93 func(*args, **kwargs)
94 except (Exception, KeyboardInterrupt):
95 if self.print_on_error:
96 print("Error in callback {} (for {}):".format(func, event))
97 self.shell.showtraceback()
99# event_name -> prototype mapping
100available_events = {}
102def _define_event(callback_function):
103 callback_proto = callback_prototype(callback_function)
104 available_events[callback_function.__name__] = callback_proto
105 return callback_proto
107# ------------------------------------------------------------------------------
108# Callback prototypes
109#
110# No-op functions which describe the names of available events and the
111# signatures of callbacks for those events.
112# ------------------------------------------------------------------------------
114@_define_event
115def pre_execute():
116 """Fires before code is executed in response to user/frontend action.
118 This includes comm and widget messages and silent execution, as well as user
119 code cells.
120 """
121 pass
123@_define_event
124def pre_run_cell(info):
125 """Fires before user-entered code runs.
127 Parameters
128 ----------
129 info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
130 An object containing information used for the code execution.
131 """
132 pass
134@_define_event
135def post_execute():
136 """Fires after code is executed in response to user/frontend action.
138 This includes comm and widget messages and silent execution, as well as user
139 code cells.
140 """
141 pass
143@_define_event
144def post_run_cell(result):
145 """Fires after user-entered code runs.
147 Parameters
148 ----------
149 result : :class:`~IPython.core.interactiveshell.ExecutionResult`
150 The object which will be returned as the execution result.
151 """
152 pass
154@_define_event
155def shell_initialized(ip):
156 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
158 This is before extensions and startup scripts are loaded, so it can only be
159 set by subclassing.
161 Parameters
162 ----------
163 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
164 The newly initialised shell.
165 """
166 pass