|
@@
-1,124
+1,129
b''
|
|
1
|
"""Infrastructure for registering and firing callbacks.
|
|
1
|
"""Infrastructure for registering and firing callbacks.
|
|
2
|
|
|
2
|
|
|
3
|
Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
|
|
3
|
Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
|
|
4
|
be called at specific times, or a collection of alternative methods to try,
|
|
4
|
be called at specific times, or a collection of alternative methods to try,
|
|
5
|
callbacks are designed to be used by extension authors. A number of callbacks
|
|
5
|
callbacks are designed to be used by extension authors. A number of callbacks
|
|
6
|
can be registered for the same event without needing to be aware of one another.
|
|
6
|
can be registered for the same event without needing to be aware of one another.
|
|
7
|
|
|
7
|
|
|
8
|
The functions defined in this module are no-ops indicating the names of available
|
|
8
|
The functions defined in this module are no-ops indicating the names of available
|
|
9
|
events and the arguments which will be passed to them.
|
|
9
|
events and the arguments which will be passed to them.
|
|
10
|
"""
|
|
10
|
"""
|
|
11
|
from __future__ import print_function
|
|
11
|
from __future__ import print_function
|
|
12
|
|
|
12
|
|
|
13
|
class CallbackManager(object):
|
|
13
|
class CallbackManager(object):
|
|
14
|
"""Manage a collection of events and a sequence of callbacks for each.
|
|
14
|
"""Manage a collection of events and a sequence of callbacks for each.
|
|
15
|
|
|
15
|
|
|
16
|
This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
|
|
16
|
This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
|
|
17
|
instances as a ``callbacks`` attribute.
|
|
17
|
instances as a ``callbacks`` attribute.
|
|
18
|
"""
|
|
18
|
"""
|
|
19
|
def __init__(self, shell, available_callbacks):
|
|
19
|
def __init__(self, shell, available_callbacks):
|
|
20
|
"""Initialise the :class:`CallbackManager`.
|
|
20
|
"""Initialise the :class:`CallbackManager`.
|
|
21
|
|
|
21
|
|
|
22
|
Parameters
|
|
22
|
Parameters
|
|
23
|
----------
|
|
23
|
----------
|
|
24
|
shell
|
|
24
|
shell
|
|
25
|
The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
|
|
25
|
The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
|
|
26
|
available_callbacks
|
|
26
|
available_callbacks
|
|
27
|
An iterable of names for callback events.
|
|
27
|
An iterable of names for callback events.
|
|
28
|
"""
|
|
28
|
"""
|
|
29
|
self.shell = shell
|
|
29
|
self.shell = shell
|
|
30
|
self.callbacks = {n:[] for n in available_callbacks}
|
|
30
|
self.callbacks = {n:[] for n in available_callbacks}
|
|
31
|
|
|
31
|
|
|
32
|
def register(self, name, function):
|
|
32
|
def register(self, name, function):
|
|
33
|
"""Register a new callback
|
|
33
|
"""Register a new callback
|
|
34
|
|
|
34
|
|
|
35
|
Parameters
|
|
35
|
Parameters
|
|
36
|
----------
|
|
36
|
----------
|
|
37
|
name : str
|
|
37
|
name : str
|
|
38
|
The event for which to register this callback.
|
|
38
|
The event for which to register this callback.
|
|
39
|
function : callable
|
|
39
|
function : callable
|
|
40
|
A function to be called on the given event. It should take the same
|
|
40
|
A function to be called on the given event. It should take the same
|
|
41
|
parameters as the appropriate callback prototype.
|
|
41
|
parameters as the appropriate callback prototype.
|
|
42
|
|
|
42
|
|
|
43
|
Raises
|
|
43
|
Raises
|
|
44
|
------
|
|
44
|
------
|
|
45
|
TypeError
|
|
45
|
TypeError
|
|
46
|
If ``function`` is not callable.
|
|
46
|
If ``function`` is not callable.
|
|
47
|
KeyError
|
|
47
|
KeyError
|
|
48
|
If ``name`` is not one of the known callback events.
|
|
48
|
If ``name`` is not one of the known callback events.
|
|
49
|
"""
|
|
49
|
"""
|
|
50
|
if not callable(function):
|
|
50
|
if not callable(function):
|
|
51
|
raise TypeError('Need a callable, got %r' % function)
|
|
51
|
raise TypeError('Need a callable, got %r' % function)
|
|
52
|
self.callbacks[name].append(function)
|
|
52
|
self.callbacks[name].append(function)
|
|
53
|
|
|
53
|
|
|
54
|
def unregister(self, name, function):
|
|
54
|
def unregister(self, name, function):
|
|
55
|
"""Remove a callback from the given event."""
|
|
55
|
"""Remove a callback from the given event."""
|
|
56
|
self.callbacks[name].remove(function)
|
|
56
|
self.callbacks[name].remove(function)
|
|
57
|
|
|
57
|
|
|
58
|
def reset(self, name):
|
|
58
|
def reset(self, name):
|
|
59
|
"""Clear all callbacks for the given event."""
|
|
59
|
"""Clear all callbacks for the given event."""
|
|
60
|
self.callbacks[name] = []
|
|
60
|
self.callbacks[name] = []
|
|
61
|
|
|
61
|
|
|
62
|
def reset_all(self):
|
|
62
|
def reset_all(self):
|
|
63
|
"""Clear all callbacks for all events."""
|
|
63
|
"""Clear all callbacks for all events."""
|
|
64
|
self.callbacks = {n:[] for n in self.callbacks}
|
|
64
|
self.callbacks = {n:[] for n in self.callbacks}
|
|
65
|
|
|
65
|
|
|
66
|
def fire(self, name, *args, **kwargs):
|
|
66
|
def fire(self, name, *args, **kwargs):
|
|
67
|
"""Call callbacks for the event ``name``.
|
|
67
|
"""Call callbacks for the event ``name``.
|
|
68
|
|
|
68
|
|
|
69
|
Any additional arguments are passed to all callbacks registered for this
|
|
69
|
Any additional arguments are passed to all callbacks registered for this
|
|
70
|
event. Exceptions raised by callbacks are caught, and a message printed.
|
|
70
|
event. Exceptions raised by callbacks are caught, and a message printed.
|
|
71
|
"""
|
|
71
|
"""
|
|
72
|
for func in self.callbacks[name]:
|
|
72
|
for func in self.callbacks[name]:
|
|
73
|
try:
|
|
73
|
try:
|
|
74
|
func(*args, **kwargs)
|
|
74
|
func(*args, **kwargs)
|
|
75
|
except Exception:
|
|
75
|
except Exception:
|
|
76
|
print("Error in callback {} (for {}):".format(func, name))
|
|
76
|
print("Error in callback {} (for {}):".format(func, name))
|
|
77
|
self.shell.showtraceback()
|
|
77
|
self.shell.showtraceback()
|
|
78
|
|
|
78
|
|
|
79
|
# event_name -> prototype mapping
|
|
79
|
# event_name -> prototype mapping
|
|
80
|
available_callbacks = {}
|
|
80
|
available_callbacks = {}
|
|
81
|
|
|
81
|
|
|
82
|
def _collect(callback_proto):
|
|
82
|
def _collect(callback_proto):
|
|
83
|
available_callbacks[callback_proto.__name__] = callback_proto
|
|
83
|
available_callbacks[callback_proto.__name__] = callback_proto
|
|
84
|
return callback_proto
|
|
84
|
return callback_proto
|
|
85
|
|
|
85
|
|
|
86
|
# ------------------------------------------------------------------------------
|
|
86
|
# ------------------------------------------------------------------------------
|
|
87
|
# Callback prototypes
|
|
87
|
# Callback prototypes
|
|
88
|
#
|
|
88
|
#
|
|
89
|
# No-op functions which describe the names of available events and the
|
|
89
|
# No-op functions which describe the names of available events and the
|
|
90
|
# signatures of callbacks for those events.
|
|
90
|
# signatures of callbacks for those events.
|
|
91
|
# ------------------------------------------------------------------------------
|
|
91
|
# ------------------------------------------------------------------------------
|
|
92
|
|
|
92
|
|
|
93
|
@_collect
|
|
93
|
@_collect
|
|
94
|
def pre_execute():
|
|
94
|
def pre_execute():
|
|
95
|
"""Fires before code is executed in response to user/frontend action.
|
|
95
|
"""Fires before code is executed in response to user/frontend action.
|
|
96
|
|
|
96
|
|
|
97
|
This includes comm and widget messages as well as user code cells."""
|
|
97
|
This includes comm and widget messages as well as user code cells."""
|
|
98
|
pass
|
|
98
|
pass
|
|
99
|
|
|
99
|
|
|
100
|
@_collect
|
|
100
|
@_collect
|
|
101
|
def pre_execute_explicit():
|
|
101
|
def pre_execute_explicit():
|
|
102
|
"""Fires before user-entered code runs."""
|
|
102
|
"""Fires before user-entered code runs."""
|
|
103
|
pass
|
|
103
|
pass
|
|
104
|
|
|
104
|
|
|
105
|
@_collect
|
|
105
|
@_collect
|
|
106
|
def post_execute():
|
|
106
|
def post_execute():
|
|
107
|
"""Fires after code is executed in response to user/frontend action.
|
|
107
|
"""Fires after code is executed in response to user/frontend action.
|
|
108
|
|
|
108
|
|
|
109
|
This includes comm and widget messages as well as user code cells."""
|
|
109
|
This includes comm and widget messages as well as user code cells."""
|
|
110
|
pass
|
|
110
|
pass
|
|
111
|
|
|
111
|
|
|
112
|
@_collect
|
|
112
|
@_collect
|
|
113
|
def post_execute_explicit():
|
|
113
|
def post_execute_explicit():
|
|
114
|
"""Fires after user-entered code runs."""
|
|
114
|
"""Fires after user-entered code runs."""
|
|
115
|
pass
|
|
115
|
pass
|
|
116
|
|
|
116
|
|
|
117
|
@_collect
|
|
117
|
@_collect
|
|
118
|
def shell_initialised(ip):
|
|
118
|
def shell_initialised(ip):
|
|
119
|
"""Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
|
|
119
|
"""Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
|
|
120
|
|
|
120
|
|
|
121
|
This is before extensions and startup scripts are loaded, so it can only be
|
|
121
|
This is before extensions and startup scripts are loaded, so it can only be
|
|
122
|
set by subclassing.
|
|
122
|
set by subclassing.
|
|
|
|
|
123
|
|
|
|
|
|
124
|
Parameters
|
|
|
|
|
125
|
----------
|
|
|
|
|
126
|
ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
|
|
|
|
|
127
|
The newly initialised shell.
|
|
123
|
"""
|
|
128
|
"""
|
|
124
|
pass
|
|
129
|
pass
|