events.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. from __future__ import print_function
  12. class EventManager(object):
  13. """Manage a collection of events and a sequence of callbacks for each.
  14. This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
  15. instances as an ``events`` attribute.
  16. .. note::
  17. This API is experimental in IPython 2.0, and may be revised in future versions.
  18. """
  19. def __init__(self, shell, available_events):
  20. """Initialise the :class:`CallbackManager`.
  21. Parameters
  22. ----------
  23. shell
  24. The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
  25. available_callbacks
  26. An iterable of names for callback events.
  27. """
  28. self.shell = shell
  29. self.callbacks = {n:[] for n in available_events}
  30. def register(self, event, function):
  31. """Register a new event callback
  32. Parameters
  33. ----------
  34. event : str
  35. The event for which to register this callback.
  36. function : callable
  37. A function to be called on the given event. It should take the same
  38. parameters as the appropriate callback prototype.
  39. Raises
  40. ------
  41. TypeError
  42. If ``function`` is not callable.
  43. KeyError
  44. If ``event`` is not one of the known events.
  45. """
  46. if not callable(function):
  47. raise TypeError('Need a callable, got %r' % function)
  48. self.callbacks[event].append(function)
  49. def unregister(self, event, function):
  50. """Remove a callback from the given event."""
  51. self.callbacks[event].remove(function)
  52. def trigger(self, event, *args, **kwargs):
  53. """Call callbacks for ``event``.
  54. Any additional arguments are passed to all callbacks registered for this
  55. event. Exceptions raised by callbacks are caught, and a message printed.
  56. """
  57. for func in self.callbacks[event][:]:
  58. try:
  59. func(*args, **kwargs)
  60. except Exception:
  61. print("Error in callback {} (for {}):".format(func, event))
  62. self.shell.showtraceback()
  63. # event_name -> prototype mapping
  64. available_events = {}
  65. def _define_event(callback_proto):
  66. available_events[callback_proto.__name__] = callback_proto
  67. return callback_proto
  68. # ------------------------------------------------------------------------------
  69. # Callback prototypes
  70. #
  71. # No-op functions which describe the names of available events and the
  72. # signatures of callbacks for those events.
  73. # ------------------------------------------------------------------------------
  74. @_define_event
  75. def pre_execute():
  76. """Fires before code is executed in response to user/frontend action.
  77. This includes comm and widget messages and silent execution, as well as user
  78. code cells."""
  79. pass
  80. @_define_event
  81. def pre_run_cell():
  82. """Fires before user-entered code runs."""
  83. pass
  84. @_define_event
  85. def post_execute():
  86. """Fires after 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. pass
  90. @_define_event
  91. def post_run_cell():
  92. """Fires after user-entered code runs."""
  93. pass
  94. @_define_event
  95. def shell_initialized(ip):
  96. """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
  97. This is before extensions and startup scripts are loaded, so it can only be
  98. set by subclassing.
  99. Parameters
  100. ----------
  101. ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
  102. The newly initialised shell.
  103. """
  104. pass