##// END OF EJS Templates
Rename callbacks -> events (mostly), fire -> trigger
Thomas Kluyver -
Show More
@@ -1,4 +1,4 b''
1 """Infrastructure for registering and firing callbacks.
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,
@@ -10,13 +10,13 b' events and the arguments which will be passed to them.'
10 10 """
11 11 from __future__ import print_function
12 12
13 class CallbackManager(object):
13 class EventManager(object):
14 14 """Manage a collection of events and a sequence of callbacks for each.
15 15
16 16 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
17 17 instances as a ``callbacks`` attribute.
18 18 """
19 def __init__(self, shell, available_callbacks):
19 def __init__(self, shell, available_events):
20 20 """Initialise the :class:`CallbackManager`.
21 21
22 22 Parameters
@@ -27,14 +27,14 b' class CallbackManager(object):'
27 27 An iterable of names for callback events.
28 28 """
29 29 self.shell = shell
30 self.callbacks = {n:[] for n in available_callbacks}
30 self.callbacks = {n:[] for n in available_events}
31 31
32 def register(self, name, function):
32 def register(self, event, function):
33 33 """Register a new callback
34 34
35 35 Parameters
36 36 ----------
37 name : str
37 event : str
38 38 The event for which to register this callback.
39 39 function : callable
40 40 A function to be called on the given event. It should take the same
@@ -45,42 +45,42 b' class CallbackManager(object):'
45 45 TypeError
46 46 If ``function`` is not callable.
47 47 KeyError
48 If ``name`` is not one of the known callback events.
48 If ``event`` is not one of the known events.
49 49 """
50 50 if not callable(function):
51 51 raise TypeError('Need a callable, got %r' % function)
52 self.callbacks[name].append(function)
52 self.callbacks[event].append(function)
53 53
54 def unregister(self, name, function):
54 def unregister(self, event, function):
55 55 """Remove a callback from the given event."""
56 self.callbacks[name].remove(function)
56 self.callbacks[event].remove(function)
57 57
58 def reset(self, name):
58 def reset(self, event):
59 59 """Clear all callbacks for the given event."""
60 self.callbacks[name] = []
60 self.callbacks[event] = []
61 61
62 62 def reset_all(self):
63 63 """Clear all callbacks for all events."""
64 64 self.callbacks = {n:[] for n in self.callbacks}
65 65
66 def fire(self, name, *args, **kwargs):
67 """Call callbacks for the event ``name``.
66 def trigger(self, event, *args, **kwargs):
67 """Call callbacks for ``event``.
68 68
69 69 Any additional arguments are passed to all callbacks registered for this
70 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[event]:
73 73 try:
74 74 func(*args, **kwargs)
75 75 except Exception:
76 print("Error in callback {} (for {}):".format(func, name))
76 print("Error in callback {} (for {}):".format(func, event))
77 77 self.shell.showtraceback()
78 78
79 79 # event_name -> prototype mapping
80 available_callbacks = {}
80 available_events = {}
81 81
82 82 def _collect(callback_proto):
83 available_callbacks[callback_proto.__name__] = callback_proto
83 available_events[callback_proto.__name__] = callback_proto
84 84 return callback_proto
85 85
86 86 # ------------------------------------------------------------------------------
@@ -41,7 +41,7 b' from IPython.core import ultratb'
41 41 from IPython.core.alias import AliasManager, AliasError
42 42 from IPython.core.autocall import ExitAutocall
43 43 from IPython.core.builtin_trap import BuiltinTrap
44 from IPython.core.callbacks import CallbackManager, available_callbacks
44 from IPython.core.events import EventManager, available_events
45 45 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
46 46 from IPython.core.display_trap import DisplayTrap
47 47 from IPython.core.displayhook import DisplayHook
@@ -468,7 +468,7 b' class InteractiveShell(SingletonConfigurable):'
468 468
469 469 self.init_syntax_highlighting()
470 470 self.init_hooks()
471 self.init_callbacks()
471 self.init_events()
472 472 self.init_pushd_popd_magic()
473 473 # self.init_traceback_handlers use to be here, but we moved it below
474 474 # because it and init_io have to come after init_readline.
@@ -512,7 +512,7 b' class InteractiveShell(SingletonConfigurable):'
512 512 self.init_payload()
513 513 self.init_comms()
514 514 self.hooks.late_startup_hook()
515 self.callbacks.fire('shell_initialised', self)
515 self.events.trigger('shell_initialised', self)
516 516 atexit.register(self.atexit_operations)
517 517
518 518 def get_ipython(self):
@@ -840,8 +840,8 b' class InteractiveShell(SingletonConfigurable):'
840 840 # Things related to callbacks
841 841 #-------------------------------------------------------------------------
842 842
843 def init_callbacks(self):
844 self.callbacks = CallbackManager(self, available_callbacks)
843 def init_events(self):
844 self.events = EventManager(self, available_events)
845 845
846 846 def register_post_execute(self, func):
847 847 """DEPRECATED: Use ip.callbacks.register('post_execute_explicit', func)
@@ -850,7 +850,7 b' class InteractiveShell(SingletonConfigurable):'
850 850 """
851 851 warn("ip.register_post_execute is deprecated, use "
852 852 "ip.callbacks.register('post_execute_explicit', func) instead.")
853 self.callbacks.register('post_execute_explicit', func)
853 self.events.register('post_execute_explicit', func)
854 854
855 855 #-------------------------------------------------------------------------
856 856 # Things related to the "main" module
@@ -2667,9 +2667,9 b' class InteractiveShell(SingletonConfigurable):'
2667 2667 if silent:
2668 2668 store_history = False
2669 2669
2670 self.callbacks.fire('pre_execute')
2670 self.events.trigger('pre_execute')
2671 2671 if not silent:
2672 self.callbacks.fire('pre_execute_explicit')
2672 self.events.trigger('pre_execute_explicit')
2673 2673
2674 2674 # If any of our input transformation (input_transformer_manager or
2675 2675 # prefilter_manager) raises an exception, we store it in this variable
@@ -2740,9 +2740,9 b' class InteractiveShell(SingletonConfigurable):'
2740 2740 self.run_ast_nodes(code_ast.body, cell_name,
2741 2741 interactivity=interactivity, compiler=compiler)
2742 2742
2743 self.callbacks.fire('post_execute')
2743 self.events.trigger('post_execute')
2744 2744 if not silent:
2745 self.callbacks.fire('post_execute_explicit')
2745 self.events.trigger('post_execute_explicit')
2746 2746
2747 2747 if store_history:
2748 2748 # Write output to the database. Does nothing unless
@@ -4,7 +4,7 b' try: # Python 3.3 +'
4 4 except ImportError:
5 5 from mock import Mock
6 6
7 from IPython.core import callbacks
7 from IPython.core import events
8 8 import IPython.testing.tools as tt
9 9
10 10 def ping_received():
@@ -12,35 +12,35 b' def ping_received():'
12 12
13 13 class CallbackTests(unittest.TestCase):
14 14 def setUp(self):
15 self.cbm = callbacks.CallbackManager(get_ipython(), {'ping_received': ping_received})
15 self.em = events.EventManager(get_ipython(), {'ping_received': ping_received})
16 16
17 17 def test_register_unregister(self):
18 18 cb = Mock()
19 19
20 self.cbm.register('ping_received', cb)
21 self.cbm.fire('ping_received')
20 self.em.register('ping_received', cb)
21 self.em.trigger('ping_received')
22 22 self.assertEqual(cb.call_count, 1)
23 23
24 self.cbm.unregister('ping_received', cb)
25 self.cbm.fire('ping_received')
24 self.em.unregister('ping_received', cb)
25 self.em.trigger('ping_received')
26 26 self.assertEqual(cb.call_count, 1)
27 27
28 28 def test_reset(self):
29 29 cb = Mock()
30 self.cbm.register('ping_received', cb)
31 self.cbm.reset('ping_received')
32 self.cbm.fire('ping_received')
30 self.em.register('ping_received', cb)
31 self.em.reset('ping_received')
32 self.em.trigger('ping_received')
33 33 assert not cb.called
34 34
35 35 def test_reset_all(self):
36 36 cb = Mock()
37 self.cbm.register('ping_received', cb)
38 self.cbm.reset_all()
39 self.cbm.fire('ping_received')
37 self.em.register('ping_received', cb)
38 self.em.reset_all()
39 self.em.trigger('ping_received')
40 40 assert not cb.called
41 41
42 42 def test_cb_error(self):
43 43 cb = Mock(side_effect=ValueError)
44 self.cbm.register('ping_received', cb)
44 self.em.register('ping_received', cb)
45 45 with tt.AssertPrints("Error in callback"):
46 self.cbm.fire('ping_received') No newline at end of file
46 self.em.trigger('ping_received') No newline at end of file
@@ -288,10 +288,10 b' class InteractiveShellTestCase(unittest.TestCase):'
288 288 post_explicit = mock.Mock()
289 289 post_always = mock.Mock()
290 290
291 ip.callbacks.register('pre_execute_explicit', pre_explicit)
292 ip.callbacks.register('pre_execute', pre_always)
293 ip.callbacks.register('post_execute_explicit', post_explicit)
294 ip.callbacks.register('post_execute', post_always)
291 ip.events.register('pre_execute_explicit', pre_explicit)
292 ip.events.register('pre_execute', pre_always)
293 ip.events.register('post_execute_explicit', post_explicit)
294 ip.events.register('post_execute', post_always)
295 295
296 296 try:
297 297 ip.run_cell("1", silent=True)
@@ -306,7 +306,7 b' class InteractiveShellTestCase(unittest.TestCase):'
306 306 assert post_explicit.called
307 307 finally:
308 308 # remove post-exec
309 ip.callbacks.reset_all()
309 ip.events.reset_all()
310 310
311 311 def test_silent_noadvance(self):
312 312 """run_cell(silent=True) doesn't advance execution_count"""
@@ -502,4 +502,4 b' def load_ipython_extension(ip):'
502 502 """Load the extension in IPython."""
503 503 auto_reload = AutoreloadMagics(ip)
504 504 ip.register_magics(auto_reload)
505 ip.callbacks.register('pre_execute_explicit', auto_reload.pre_execute_explicit)
505 ip.events.register('pre_execute_explicit', auto_reload.pre_execute_explicit)
@@ -23,7 +23,7 b' import nose.tools as nt'
23 23 import IPython.testing.tools as tt
24 24
25 25 from IPython.extensions.autoreload import AutoreloadMagics
26 from IPython.core.callbacks import CallbackManager, pre_execute_explicit
26 from IPython.core.events import EventManager, pre_execute_explicit
27 27 from IPython.utils.py3compat import PY3
28 28
29 29 if PY3:
@@ -41,14 +41,14 b' class FakeShell(object):'
41 41
42 42 def __init__(self):
43 43 self.ns = {}
44 self.callbacks = CallbackManager(self, {'pre_execute_explicit', pre_execute_explicit})
44 self.events = EventManager(self, {'pre_execute_explicit', pre_execute_explicit})
45 45 self.auto_magics = AutoreloadMagics(shell=self)
46 self.callbacks.register('pre_execute_explicit', self.auto_magics.pre_execute_explicit)
46 self.events.register('pre_execute_explicit', self.auto_magics.pre_execute_explicit)
47 47
48 48 register_magics = set_hook = noop
49 49
50 50 def run_code(self, code):
51 self.callbacks.fire('pre_execute_explicit')
51 self.events.trigger('pre_execute_explicit')
52 52 exec(code, self.ns)
53 53
54 54 def push(self, items):
@@ -134,9 +134,9 b' class Comm(LoggingConfigurable):'
134 134 """Handle a comm_msg message"""
135 135 self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
136 136 if self._msg_callback:
137 self.shell.callbacks.fire('pre_execute')
137 self.shell.events.trigger('pre_execute')
138 138 self._msg_callback(msg)
139 self.shell.callbacks.fire('post_execute')
139 self.shell.events.trigger('post_execute')
140 140
141 141
142 142 __all__ = ['Comm']
General Comments 0
You need to be logged in to leave comments. Login now