ipython/ipython — pull request #5188 by takluyver (2014-02-21 20:02:09+00:00)
Title: New callbacks system

As discussed in #5122, there's a need for a richer set of callbacks. This is the initial architecture and a few callbacks.

- `ip.callbacks` is an instance of `CallbackManager` (I know @ivanov will love this name)
- There is a set of known events, each with a name, e.g. 'pre_execute_explicit', and a signature, defined by a prototype function in `IPython.core.callbacks`.
- At present, there's no checking of signatures, but I've deliberately designed things so we could use something like [backcall](https://pypi.python.org/pypi/backcall) to verify them.
- Callbacks are registered and unregistered by passing the event name and the callback function. There's no explicit provision for unregistering a callback without a reference to the function, but you can clear all callbacks for a given event.
- Our code calls `ip.callbacks.fire('event_name', *args, **kwargs)`. Again, there's not yet any checking that the args passed match the specified signature, but there easily could be in the future.
- Exceptions raised by callbacks are displayed, but do not prevent other callbacks from executing.

I've deprecated a couple of hooks in favour of callbacks. Our hooks system is designed for end users to customise things that shouldn't be repeated if they succeed - e.g. 'load this in an editor' or 'get text from the clipboard'. In contrast, callbacks are for extension code listening for particular events, so it should be possible to register several callbacks for the same event without them interfering with one another.