##// END OF EJS Templates
Add option to EventManager to prevent printing
Tim Nonet -
Show More
@@ -1,161 +1,166 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 10
11 11 .. note::
12 12
13 13 This API is experimental in IPython 2.0, and may be revised in future versions.
14 14 """
15 15
16 16 from backcall import callback_prototype
17 17
18 18
19 19 class EventManager(object):
20 20 """Manage a collection of events and a sequence of callbacks for each.
21 21
22 22 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
23 23 instances as an ``events`` attribute.
24 24
25 25 .. note::
26 26
27 27 This API is experimental in IPython 2.0, and may be revised in future versions.
28 28 """
29 def __init__(self, shell, available_events):
29
30 def __init__(self, shell, available_events, print_on_error=True):
30 31 """Initialise the :class:`CallbackManager`.
31 32
32 33 Parameters
33 34 ----------
34 35 shell
35 36 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
36 37 available_events
37 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.
38 41 """
39 42 self.shell = shell
40 43 self.callbacks = {n:[] for n in available_events}
44 self.print_on_error = print_on_error
41 45
42 46 def register(self, event, function):
43 47 """Register a new event callback.
44 48
45 49 Parameters
46 50 ----------
47 51 event : str
48 52 The event for which to register this callback.
49 53 function : callable
50 54 A function to be called on the given event. It should take the same
51 55 parameters as the appropriate callback prototype.
52 56
53 57 Raises
54 58 ------
55 59 TypeError
56 60 If ``function`` is not callable.
57 61 KeyError
58 62 If ``event`` is not one of the known events.
59 63 """
60 64 if not callable(function):
61 65 raise TypeError('Need a callable, got %r' % function)
62 66 callback_proto = available_events.get(event)
63 67 if function not in self.callbacks[event]:
64 68 self.callbacks[event].append(callback_proto.adapt(function))
65 69
66 70 def unregister(self, event, function):
67 71 """Remove a callback from the given event."""
68 72 if function in self.callbacks[event]:
69 73 return self.callbacks[event].remove(function)
70 74
71 75 # Remove callback in case ``function`` was adapted by `backcall`.
72 76 for callback in self.callbacks[event]:
73 77 try:
74 78 if callback.__wrapped__ is function:
75 79 return self.callbacks[event].remove(callback)
76 80 except AttributeError:
77 81 pass
78 82
79 83 raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
80 84
81 85 def trigger(self, event, *args, **kwargs):
82 86 """Call callbacks for ``event``.
83 87
84 88 Any additional arguments are passed to all callbacks registered for this
85 89 event. Exceptions raised by callbacks are caught, and a message printed.
86 90 """
87 91 for func in self.callbacks[event][:]:
88 92 try:
89 93 func(*args, **kwargs)
90 94 except (Exception, KeyboardInterrupt):
91 print("Error in callback {} (for {}):".format(func, event))
95 if self.print_on_error:
96 print("Error in callback {} (for {}):".format(func, event))
92 97 self.shell.showtraceback()
93 98
94 99 # event_name -> prototype mapping
95 100 available_events = {}
96 101
97 102 def _define_event(callback_function):
98 103 callback_proto = callback_prototype(callback_function)
99 104 available_events[callback_function.__name__] = callback_proto
100 105 return callback_proto
101 106
102 107 # ------------------------------------------------------------------------------
103 108 # Callback prototypes
104 109 #
105 110 # No-op functions which describe the names of available events and the
106 111 # signatures of callbacks for those events.
107 112 # ------------------------------------------------------------------------------
108 113
109 114 @_define_event
110 115 def pre_execute():
111 116 """Fires before code is executed in response to user/frontend action.
112 117
113 118 This includes comm and widget messages and silent execution, as well as user
114 119 code cells.
115 120 """
116 121 pass
117 122
118 123 @_define_event
119 124 def pre_run_cell(info):
120 125 """Fires before user-entered code runs.
121 126
122 127 Parameters
123 128 ----------
124 129 info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
125 130 An object containing information used for the code execution.
126 131 """
127 132 pass
128 133
129 134 @_define_event
130 135 def post_execute():
131 136 """Fires after code is executed in response to user/frontend action.
132 137
133 138 This includes comm and widget messages and silent execution, as well as user
134 139 code cells.
135 140 """
136 141 pass
137 142
138 143 @_define_event
139 144 def post_run_cell(result):
140 145 """Fires after user-entered code runs.
141 146
142 147 Parameters
143 148 ----------
144 149 result : :class:`~IPython.core.interactiveshell.ExecutionResult`
145 150 The object which will be returned as the execution result.
146 151 """
147 152 pass
148 153
149 154 @_define_event
150 155 def shell_initialized(ip):
151 156 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
152 157
153 158 This is before extensions and startup scripts are loaded, so it can only be
154 159 set by subclassing.
155 160
156 161 Parameters
157 162 ----------
158 163 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
159 164 The newly initialised shell.
160 165 """
161 166 pass
General Comments 0
You need to be logged in to leave comments. Login now