============================== The magic commands subsystem ============================== .. warning:: These are *preliminary* notes and thoughts on the magic system, kept here for reference so we can come up with a good design now that the major core refactoring has made so much progress. Do not consider yet any part of this document final. Two entry points: - m.line_eval(self,parameter_s): like today - m.block_eval(self,code_block): for whole-block evaluation. This would allow us to have magics that take input, and whose single line form can even take input and call block_eval later (like %cpaste does, but with a generalized interface). Constructor =========== Suggested syntax:: class MyMagic(BaseMagic): requires_shell = True/False def __init__(self,shell=None): Registering magics ================== Today, ipapi provides an *expose_magic()* function for making simple magics. We will probably extend this (in a backwards-compatible manner if possible) to allow the simplest cases to work as today, while letting users register more complex ones. Use cases:: def func(arg): pass # note signature, no 'self' ip.expose_magic('name',func) def func_line(arg): pass def func_block(arg):pass ip.expose_magic('name',func_line,func_block) class mymagic(BaseMagic): """Magic docstring, used in help messages. """ def line_eval(self,arg): pass def block_eval(self,arg): pass ip.register_magic(mymagic) The BaseMagic class will offer common functionality to all, including things like options handling (via argparse). Call forms: line and block ========================== Block-oriented environments will call line_eval() for the first line of input (the call line starting with '%') and will then feed the rest of the block to block_eval() if the magic in question has a block mode. In line environments, by default %foo -> foo.line_eval(), but no block call is made. Specific implementations of line_eval can decide to then call block_eval if they want to provide for whole-block input in line-oriented environments. The api might be adapted for this decision to be made automatically by the frontend... Precompiled magics for rapid loading ==================================== For IPython itself, we'll have a module of 'core' magic functions that do not require run-time registration. These will be the ones contained today in Magic.py, plus any others we deem worthy of being available by default. This is a trick to enable faster startup, since once we move to a model where each magic can in principle be registered at runtime, creating a lot of them can easily swamp startup time. The trick is to make a module with a top-level class object that contains explicit references to all the 'core' magics in its dict. This way, the magic table can be quickly updated at interpreter startup with a single call, by doing something along the lines of:: self.magic_table.update(static_magics.__dict__) The point will be to be able to bypass the explicit calling of whatever register_magic() API we end up making for users to declare their own magics. So ultimately one should be able to do either:: ip.register_magic(mymagic) # for one function or:: ip.load_magics(static_magics) # for a bunch of them I still need to clarify exactly how this should work though.