##// END OF EJS Templates
Add note about experimental API
Thomas Kluyver -
Show More
@@ -1,129 +1,137 b''
1 1 """Infrastructure for registering and firing callbacks on application events.
2 2
3 3 Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
4 4 be called at specific times, or a collection of alternative methods to try,
5 5 callbacks are designed to be used by extension authors. A number of callbacks
6 6 can be registered for the same event without needing to be aware of one another.
7 7
8 8 The functions defined in this module are no-ops indicating the names of available
9 9 events and the arguments which will be passed to them.
10
11 .. note::
12
13 This API is experimental in IPython 2.0, and may be revised in future versions.
10 14 """
11 15 from __future__ import print_function
12 16
13 17 class EventManager(object):
14 18 """Manage a collection of events and a sequence of callbacks for each.
15 19
16 20 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
17 21 instances as a ``callbacks`` attribute.
22
23 .. note::
24
25 This API is experimental in IPython 2.0, and may be revised in future versions.
18 26 """
19 27 def __init__(self, shell, available_events):
20 28 """Initialise the :class:`CallbackManager`.
21 29
22 30 Parameters
23 31 ----------
24 32 shell
25 33 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
26 34 available_callbacks
27 35 An iterable of names for callback events.
28 36 """
29 37 self.shell = shell
30 38 self.callbacks = {n:[] for n in available_events}
31 39
32 40 def register(self, event, function):
33 41 """Register a new callback
34 42
35 43 Parameters
36 44 ----------
37 45 event : str
38 46 The event for which to register this callback.
39 47 function : callable
40 48 A function to be called on the given event. It should take the same
41 49 parameters as the appropriate callback prototype.
42 50
43 51 Raises
44 52 ------
45 53 TypeError
46 54 If ``function`` is not callable.
47 55 KeyError
48 56 If ``event`` is not one of the known events.
49 57 """
50 58 if not callable(function):
51 59 raise TypeError('Need a callable, got %r' % function)
52 60 self.callbacks[event].append(function)
53 61
54 62 def unregister(self, event, function):
55 63 """Remove a callback from the given event."""
56 64 self.callbacks[event].remove(function)
57 65
58 66 def reset(self, event):
59 67 """Clear all callbacks for the given event."""
60 68 self.callbacks[event] = []
61 69
62 70 def reset_all(self):
63 71 """Clear all callbacks for all events."""
64 72 self.callbacks = {n:[] for n in self.callbacks}
65 73
66 74 def trigger(self, event, *args, **kwargs):
67 75 """Call callbacks for ``event``.
68 76
69 77 Any additional arguments are passed to all callbacks registered for this
70 78 event. Exceptions raised by callbacks are caught, and a message printed.
71 79 """
72 80 for func in self.callbacks[event]:
73 81 try:
74 82 func(*args, **kwargs)
75 83 except Exception:
76 84 print("Error in callback {} (for {}):".format(func, event))
77 85 self.shell.showtraceback()
78 86
79 87 # event_name -> prototype mapping
80 88 available_events = {}
81 89
82 90 def _collect(callback_proto):
83 91 available_events[callback_proto.__name__] = callback_proto
84 92 return callback_proto
85 93
86 94 # ------------------------------------------------------------------------------
87 95 # Callback prototypes
88 96 #
89 97 # No-op functions which describe the names of available events and the
90 98 # signatures of callbacks for those events.
91 99 # ------------------------------------------------------------------------------
92 100
93 101 @_collect
94 102 def pre_execute():
95 103 """Fires before code is executed in response to user/frontend action.
96 104
97 105 This includes comm and widget messages as well as user code cells."""
98 106 pass
99 107
100 108 @_collect
101 109 def pre_execute_explicit():
102 110 """Fires before user-entered code runs."""
103 111 pass
104 112
105 113 @_collect
106 114 def post_execute():
107 115 """Fires after code is executed in response to user/frontend action.
108 116
109 117 This includes comm and widget messages as well as user code cells."""
110 118 pass
111 119
112 120 @_collect
113 121 def post_execute_explicit():
114 122 """Fires after user-entered code runs."""
115 123 pass
116 124
117 125 @_collect
118 126 def shell_initialised(ip):
119 127 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
120 128
121 129 This is before extensions and startup scripts are loaded, so it can only be
122 130 set by subclassing.
123 131
124 132 Parameters
125 133 ----------
126 134 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
127 135 The newly initialised shell.
128 136 """
129 137 pass
@@ -1,38 +1,42 b''
1 1 =====================
2 2 Registering callbacks
3 3 =====================
4 4
5 5 Extension code can register callbacks functions which will be called on specific
6 6 events within the IPython code. You can see the current list of available
7 7 callbacks, and the parameters that will be passed with each, in the callback
8 8 prototype functions defined in :mod:`IPython.core.callbacks`.
9 9
10 10 To register callbacks, use :meth:`IPython.core.callbacks.CallbackManager.register`.
11 11 For example::
12 12
13 13 class VarWatcher(object):
14 14 def __init__(self, ip):
15 15 self.shell = ip
16 16 self.last_x = None
17 17
18 18 def pre_execute(self):
19 19 self.last_x = self.shell.user_ns.get('x', None)
20 20
21 21 def post_execute(self):
22 22 if self.shell.user_ns.get('x', None) != self.last_x:
23 23 print("x changed!")
24 24
25 25 def load_ipython_extension(ip):
26 26 vw = VarWatcher(ip)
27 27 ip.callbacks.register('pre_execute', vw.pre_execute)
28 28 ip.callbacks.register('post_execute', vw.post_execute)
29 29
30 .. note::
31
32 This API is experimental in IPython 2.0, and may be revised in future versions.
33
30 34 .. seealso::
31 35
32 36 Module :mod:`IPython.core.hooks`
33 37 The older 'hooks' system allows end users to customise some parts of
34 38 IPython's behaviour.
35 39
36 40 :doc:`inputtransforms`
37 41 By registering input transformers that don't change code, you can monitor
38 42 what is being executed.
General Comments 0
You need to be logged in to leave comments. Login now