forked from ipython/ipython
-
Notifications
You must be signed in to change notification settings - Fork 0
/
magic.py
171 lines (136 loc) · 5.23 KB
/
magic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# 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.iplib import InteractiveShell
from IPython.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="<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
if '_ip.magic("%autopx' in source or '_ip.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