events.py 5.1 KB

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