diff --git a/IPython/extensions/cluster_magic.py b/IPython/extensions/cluster_magic.py new file mode 100644 index 0000000..fb8fa37 --- /dev/null +++ b/IPython/extensions/cluster_magic.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Magic command interface for interactive parallel work.""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from IPython.core.component import Component +from IPython.utils.traitlets import Bool, Any +from IPython.utils.autoattr import auto_attr + + +#------------------------------------------------------------------------------- +# Definitions of magic functions for use with IPython +#------------------------------------------------------------------------------- + +NO_ACTIVE_MULTIENGINE_CLIENT = """ +Error: No Controller is activated +Use activate() on a MultiEngineClient object to activate it for magics. +""" + + +class ParalleMagicComponent(Component): + + active_multiengine_client = Any() + verbose = Bool(False, config=True) + + def __init__(self, parent, name=None, config=None): + super(ParalleMagicComponent, self).__init__(parent, name=name, config=config) + self._define_magics() + + # Access other components like this rather than by a regular attribute. + # This won't lookup the InteractiveShell object until it is used and + # then it is cached. This is both efficient and couples this class + # more loosely to InteractiveShell. + @auto_attr + def shell(self): + return Component.get_instances( + root=self.root, + klass='IPython.core.iplib.InteractiveShell')[0] + + def _define_magics(self): + self.shell.define_magic('result', self.magic_result) + self.shell.define_magic('px', self.magic_px) + self.shell.define_magic('autopx', self.magix_autopx) + + def magic_result(self, ipself, parameter_s=''): + """Print the result of command i on all engines of the active controller. + + To activate a controller in IPython, first create it and then call + the activate() method. + + Then you can do the following: + + >>> result # Print the latest result + Printing result... + [127.0.0.1:0] In [1]: b = 10 + [127.0.0.1:1] In [1]: b = 10 + + >>> result 0 # Print result 0 + In [14]: result 0 + Printing result... + [127.0.0.1:0] In [0]: a = 5 + [127.0.0.1:1] In [0]: a = 5 + """ + if self.active_multiengine_client is None: + print NO_ACTIVE_MULTIENGINE_CLIENT + return + + try: + index = int(parameter_s) + except: + index = None + result = self.active_multiengine_client.get_result(index) + return result + + # def magic_px(self,parameter_s=''): + # """Executes the given python command on the active IPython Controller. + # + # To activate a Controller in IPython, first create it and then call + # the activate() method. + # + # Then you can do the following: + # + # >>> %px a = 5 # Runs a = 5 on all nodes + # """ + # + # try: + # activeController = __IPYTHON__.activeController + # except AttributeError: + # print NO_ACTIVE_CONTROLLER + # else: + # print "Parallel execution on engines: %s" % activeController.targets + # result = activeController.execute(parameter_s) + # return result + # + # def pxrunsource(self, source, filename="", symbol="single"): + # + # try: + # code = self.compile(source, filename, symbol) + # except (OverflowError, SyntaxError, ValueError): + # # Case 1 + # self.showsyntaxerror(filename) + # return None + # + # if code is None: + # # Case 2 + # return True + # + # # Case 3 + # # Because autopx is enabled, we now call executeAll or disable autopx if + # # %autopx or autopx has been called + # if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source: + # _disable_autopx(self) + # return False + # else: + # try: + # result = self.activeController.execute(source) + # except: + # self.showtraceback() + # else: + # print result.__repr__() + # return False + # + # def magic_autopx(self, parameter_s=''): + # """Toggles auto parallel mode for the active IPython Controller. + # + # To activate a Controller in IPython, first create it and then call + # the activate() method. + # + # Then you can do the following: + # + # >>> %autopx # Now all commands are executed in parallel + # Auto Parallel Enabled + # Type %autopx to disable + # ... + # >>> %autopx # Now all commands are locally executed + # Auto Parallel Disabled + # """ + # + # if hasattr(self, 'autopx'): + # if self.autopx == True: + # _disable_autopx(self) + # else: + # _enable_autopx(self) + # else: + # _enable_autopx(self) + # + # def _enable_autopx(self): + # """Enable %autopx mode by saving the original runsource and installing + # pxrunsource. + # """ + # try: + # activeController = __IPYTHON__.activeController + # except AttributeError: + # print "No active RemoteController found, use RemoteController.activate()." + # else: + # self._original_runsource = self.runsource + # self.runsource = new.instancemethod(pxrunsource, self, self.__class__) + # self.autopx = True + # print "Auto Parallel Enabled\nType %autopx to disable" + # + # def _disable_autopx(self): + # """Disable %autopx by restoring the original runsource.""" + # if hasattr(self, 'autopx'): + # if self.autopx == True: + # self.runsource = self._original_runsource + # self.autopx = False + # print "Auto Parallel Disabled" + + +_loaded = False + +def load_ipython_extension(ip): + """Load the extension in IPython as a hook.""" + global _loaded + if not _loaded: + prd = ParalleMagicComponent(ip, name='parallel_magic') + _loaded = True + diff --git a/IPython/kernel/magic.py b/IPython/kernel/magic.py deleted file mode 100644 index 0d40f6a..0000000 --- a/IPython/kernel/magic.py +++ /dev/null @@ -1,171 +0,0 @@ -# encoding: utf-8 - -"""Magic command interface for interactive parallel work.""" - -__docformat__ = "restructuredtext en" - -#------------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# Imports -#------------------------------------------------------------------------------- - -import new - -from IPython.core.iplib import InteractiveShell -from IPython.core.shell import MTInteractiveShell - -from twisted.internet.defer import Deferred - - -#------------------------------------------------------------------------------- -# Definitions of magic functions for use with IPython -#------------------------------------------------------------------------------- - -NO_ACTIVE_CONTROLLER = """ -Error: No Controller is activated -Use activate() on a RemoteController object to activate it for magics. -""" - -def magic_result(self,parameter_s=''): - """Print the result of command i on all engines of the active controller. - - To activate a controller in IPython, first create it and then call - the activate() method. - - Then you can do the following: - - >>> result # Print the latest result - Printing result... - [127.0.0.1:0] In [1]: b = 10 - [127.0.0.1:1] In [1]: b = 10 - - >>> result 0 # Print result 0 - In [14]: result 0 - Printing result... - [127.0.0.1:0] In [0]: a = 5 - [127.0.0.1:1] In [0]: a = 5 - """ - try: - activeController = __IPYTHON__.activeController - except AttributeError: - print NO_ACTIVE_CONTROLLER - else: - try: - index = int(parameter_s) - except: - index = None - result = activeController.get_result(index) - return result - -def magic_px(self,parameter_s=''): - """Executes the given python command on the active IPython Controller. - - To activate a Controller in IPython, first create it and then call - the activate() method. - - Then you can do the following: - - >>> %px a = 5 # Runs a = 5 on all nodes - """ - - try: - activeController = __IPYTHON__.activeController - except AttributeError: - print NO_ACTIVE_CONTROLLER - else: - print "Parallel execution on engines: %s" % activeController.targets - result = activeController.execute(parameter_s) - return result - -def pxrunsource(self, source, filename="", symbol="single"): - - try: - code = self.compile(source, filename, symbol) - except (OverflowError, SyntaxError, ValueError): - # Case 1 - self.showsyntaxerror(filename) - return None - - if code is None: - # Case 2 - return True - - # Case 3 - # Because autopx is enabled, we now call executeAll or disable autopx if - # %autopx or autopx has been called - if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source: - _disable_autopx(self) - return False - else: - try: - result = self.activeController.execute(source) - except: - self.showtraceback() - else: - print result.__repr__() - return False - -def magic_autopx(self, parameter_s=''): - """Toggles auto parallel mode for the active IPython Controller. - - To activate a Controller in IPython, first create it and then call - the activate() method. - - Then you can do the following: - - >>> %autopx # Now all commands are executed in parallel - Auto Parallel Enabled - Type %autopx to disable - ... - >>> %autopx # Now all commands are locally executed - Auto Parallel Disabled - """ - - if hasattr(self, 'autopx'): - if self.autopx == True: - _disable_autopx(self) - else: - _enable_autopx(self) - else: - _enable_autopx(self) - -def _enable_autopx(self): - """Enable %autopx mode by saving the original runsource and installing - pxrunsource. - """ - try: - activeController = __IPYTHON__.activeController - except AttributeError: - print "No active RemoteController found, use RemoteController.activate()." - else: - self._original_runsource = self.runsource - self.runsource = new.instancemethod(pxrunsource, self, self.__class__) - self.autopx = True - print "Auto Parallel Enabled\nType %autopx to disable" - -def _disable_autopx(self): - """Disable %autopx by restoring the original runsource.""" - if hasattr(self, 'autopx'): - if self.autopx == True: - self.runsource = self._original_runsource - self.autopx = False - print "Auto Parallel Disabled" - -# Add the new magic function to the class dict: - -InteractiveShell.magic_result = magic_result -InteractiveShell.magic_px = magic_px -InteractiveShell.magic_autopx = magic_autopx - -# And remove the global name to keep global namespace clean. Don't worry, the -# copy bound to IPython stays, we're just removing the global name. -del magic_result -del magic_px -del magic_autopx -