Make comm manager (mostly) independent of InteractiveShell

This makes it possible to use comms from wrapper kernels, without instantiating the full IPython shell machinery.

The one remaining place where we need a reference to shell is to fire pre_execute and post_execute hooks (which are needed to get mpl figures right). This is a pure IPythonism, that it should be safe to ignore if shell is not set.

Ping @dsblank - you were asking about this in #6314.
Since kernel is a singleton, the default for `.kernel` should retrieve the instance anyway. Though if people instantiate it by calling the class, that doesn't register the singleton instance. I guess I'll put in the safeguard...