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