magic.py
171 lines
| 5.3 KiB
| text/x-python
|
PythonLexer
Brian E Granger
|
r1234 | # 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 | ||||
Brian Granger
|
r2028 | from IPython.core.iplib import InteractiveShell | ||
Brian Granger
|
r2046 | from IPython.core.shell import MTInteractiveShell | ||
Brian E Granger
|
r1234 | |||
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: | ||||
Brian E Granger
|
r1395 | print "Parallel execution on engines: %s" % activeController.targets | ||
Brian E Granger
|
r1234 | result = activeController.execute(parameter_s) | ||
return result | ||||
def pxrunsource(self, source, filename="<input>", 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 | ||||
Brian Granger
|
r2245 | if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source: | ||
Brian E Granger
|
r1234 | _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 | ||||