IPython’s own magics are now declared lazily. Starting a shell used to import
all fifteen modules under IPython.core.magics and instantiate every
Magics class in them, even though a session
typically uses a handful of magics at most. Only the magic names are now known
up front, from a hand-maintained table in IPython.core.magics._table, and the
module implementing a magic is imported the first time it is looked up. This
takes roughly 25 ms off import IPython and shell startup.
This reuses lazy_magics, which already
existed for extensions, so third-party code can declare its magics the same way:
shell.magics_manager.register_lazy("my_magic", "my_package.magics:MyMagics")
Its values may now be either "package.module", loaded as an IPython extension
as before, or "package.module:MagicsClass", imported and registered directly.
Unlike before, a magic declared through
register_lazy() shows up in %lsmagic
and in completion right away rather than only after its first use.
Until a magic is loaded, shell.magics_manager.magics[kind][name] holds a
LazyMagic placeholder. Calling it, or reading any
attribute of it, loads and delegates to the real magic, so existing code that
reaches into that table keeps working. A magics class only appears in
shell.configurables once loaded; %config loads everything first, so the
list of configurable classes it shows is unchanged.