Show More
@@ -14,7 +14,9 b'' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
|
17 | import ast | |||
17 | import new |
|
18 | import new | |
|
19 | import re | |||
18 |
|
20 | |||
19 | from IPython.core.plugin import Plugin |
|
21 | from IPython.core.plugin import Plugin | |
20 | from IPython.utils.traitlets import Bool, Any, Instance |
|
22 | from IPython.utils.traitlets import Bool, Any, Instance | |
@@ -26,15 +28,15 b' from IPython.testing import decorators as testdec' | |||||
26 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
27 |
|
29 | |||
28 |
|
30 | |||
29 |
NO_ACTIVE_ |
|
31 | NO_ACTIVE_VIEW = """ | |
30 |
Use activate() on a |
|
32 | Use activate() on a DirectView object to activate it for magics. | |
31 | """ |
|
33 | """ | |
32 |
|
34 | |||
33 |
|
35 | |||
34 | class ParalleMagic(Plugin): |
|
36 | class ParalleMagic(Plugin): | |
35 | """A component to manage the %result, %px and %autopx magics.""" |
|
37 | """A component to manage the %result, %px and %autopx magics.""" | |
36 |
|
38 | |||
37 |
active_ |
|
39 | active_view = Any() | |
38 | verbose = Bool(False, config=True) |
|
40 | verbose = Bool(False, config=True) | |
39 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
41 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
40 |
|
42 | |||
@@ -54,7 +56,7 b' class ParalleMagic(Plugin):' | |||||
54 | def magic_result(self, ipself, parameter_s=''): |
|
56 | def magic_result(self, ipself, parameter_s=''): | |
55 | """Print the result of command i on all engines.. |
|
57 | """Print the result of command i on all engines.. | |
56 |
|
58 | |||
57 |
To use this a :class:` |
|
59 | To use this a :class:`DirectView` instance must be created | |
58 | and then activated by calling its :meth:`activate` method. |
|
60 | and then activated by calling its :meth:`activate` method. | |
59 |
|
61 | |||
60 | Then you can do the following:: |
|
62 | Then you can do the following:: | |
@@ -71,22 +73,22 b' class ParalleMagic(Plugin):' | |||||
71 | [0] In [6]: a = 10 |
|
73 | [0] In [6]: a = 10 | |
72 | [1] In [6]: a = 10 |
|
74 | [1] In [6]: a = 10 | |
73 | """ |
|
75 | """ | |
74 |
if self.active_ |
|
76 | if self.active_view is None: | |
75 |
print NO_ACTIVE_ |
|
77 | print NO_ACTIVE_VIEW | |
76 | return |
|
78 | return | |
77 |
|
79 | |||
78 | try: |
|
80 | try: | |
79 | index = int(parameter_s) |
|
81 | index = int(parameter_s) | |
80 | except: |
|
82 | except: | |
81 | index = None |
|
83 | index = None | |
82 |
result = self.active_ |
|
84 | result = self.active_view.get_result(index) | |
83 | return result |
|
85 | return result | |
84 |
|
86 | |||
85 | @testdec.skip_doctest |
|
87 | @testdec.skip_doctest | |
86 | def magic_px(self, ipself, parameter_s=''): |
|
88 | def magic_px(self, ipself, parameter_s=''): | |
87 | """Executes the given python command in parallel. |
|
89 | """Executes the given python command in parallel. | |
88 |
|
90 | |||
89 |
To use this a :class:` |
|
91 | To use this a :class:`DirectView` instance must be created | |
90 | and then activated by calling its :meth:`activate` method. |
|
92 | and then activated by calling its :meth:`activate` method. | |
91 |
|
93 | |||
92 | Then you can do the following:: |
|
94 | Then you can do the following:: | |
@@ -99,18 +101,18 b' class ParalleMagic(Plugin):' | |||||
99 | [1] In [7]: a = 5 |
|
101 | [1] In [7]: a = 5 | |
100 | """ |
|
102 | """ | |
101 |
|
103 | |||
102 |
if self.active_ |
|
104 | if self.active_view is None: | |
103 |
print NO_ACTIVE_ |
|
105 | print NO_ACTIVE_VIEW | |
104 | return |
|
106 | return | |
105 |
print "Parallel execution on engines: %s" % self.active_ |
|
107 | print "Parallel execution on engines: %s" % self.active_view.targets | |
106 |
result = self.active_ |
|
108 | result = self.active_view.execute(parameter_s) | |
107 | return result |
|
109 | return result | |
108 |
|
110 | |||
109 | @testdec.skip_doctest |
|
111 | @testdec.skip_doctest | |
110 | def magic_autopx(self, ipself, parameter_s=''): |
|
112 | def magic_autopx(self, ipself, parameter_s=''): | |
111 | """Toggles auto parallel mode. |
|
113 | """Toggles auto parallel mode. | |
112 |
|
114 | |||
113 |
To use this a :class:` |
|
115 | To use this a :class:`DirectView` instance must be created | |
114 | and then activated by calling its :meth:`activate` method. Once this |
|
116 | and then activated by calling its :meth:`activate` method. Once this | |
115 | is called, all commands typed at the command line are send to |
|
117 | is called, all commands typed at the command line are send to | |
116 | the engines to be executed in parallel. To control which engine |
|
118 | the engines to be executed in parallel. To control which engine | |
@@ -137,67 +139,89 b' class ParalleMagic(Plugin):' | |||||
137 | self._enable_autopx() |
|
139 | self._enable_autopx() | |
138 |
|
140 | |||
139 | def _enable_autopx(self): |
|
141 | def _enable_autopx(self): | |
140 |
"""Enable %autopx mode by saving the original run_ |
|
142 | """Enable %autopx mode by saving the original run_cell and installing | |
141 |
pxrun_ |
|
143 | pxrun_cell. | |
142 | """ |
|
144 | """ | |
143 |
if self.active_ |
|
145 | if self.active_view is None: | |
144 |
print NO_ACTIVE_ |
|
146 | print NO_ACTIVE_VIEW | |
145 | return |
|
147 | return | |
146 |
|
148 | |||
147 |
self._original_run_ |
|
149 | self._original_run_cell = self.shell.run_cell | |
148 |
self.shell.run_ |
|
150 | self.shell.run_cell = new.instancemethod( | |
149 |
self.pxrun_ |
|
151 | self.pxrun_cell, self.shell, self.shell.__class__ | |
150 | ) |
|
152 | ) | |
151 | self.autopx = True |
|
153 | self.autopx = True | |
152 | print "%autopx enabled" |
|
154 | print "%autopx enabled" | |
153 |
|
155 | |||
154 | def _disable_autopx(self): |
|
156 | def _disable_autopx(self): | |
155 |
"""Disable %autopx by restoring the original InteractiveShell.run_ |
|
157 | """Disable %autopx by restoring the original InteractiveShell.run_cell. | |
156 | """ |
|
158 | """ | |
157 | if self.autopx: |
|
159 | if self.autopx: | |
158 |
self.shell.run_ |
|
160 | self.shell.run_cell = self._original_run_cell | |
159 | self.autopx = False |
|
161 | self.autopx = False | |
160 | print "%autopx disabled" |
|
162 | print "%autopx disabled" | |
161 |
|
163 | |||
162 |
def pxrun_ |
|
164 | def pxrun_cell(self, ipself, cell, store_history=True): | |
163 | symbol='single', post_execute=True): |
|
165 | """drop-in replacement for InteractiveShell.run_cell. | |
164 |
|
166 | |||
165 | # We need to ensure that the source is unicode from here on. |
|
167 | This executes code remotely, instead of in the local namespace. | |
166 | if type(source)==str: |
|
168 | """ | |
167 | usource = source.decode(ipself.stdin_encoding) |
|
169 | raw_cell = cell | |
168 | else: |
|
170 | with ipself.builtin_trap: | |
169 | usource = source |
|
171 | cell = ipself.prefilter_manager.prefilter_lines(cell) | |
|
172 | ||||
|
173 | # Store raw and processed history | |||
|
174 | if store_history: | |||
|
175 | ipself.history_manager.store_inputs(ipself.execution_count, | |||
|
176 | cell, raw_cell) | |||
170 |
|
177 | |||
171 | if 0: # dbg |
|
178 | # ipself.logger.log(cell, raw_cell) | |
172 | print 'Source:', repr(source) # dbg |
|
|||
173 | print 'USource:', repr(usource) # dbg |
|
|||
174 | print 'type:', type(source) # dbg |
|
|||
175 | print 'encoding', ipself.stdin_encoding # dbg |
|
|||
176 |
|
179 | |||
177 | try: |
|
180 | cell_name = ipself.compile.cache(cell, ipself.execution_count) | |
178 | code = ipself.compile(usource, symbol, ipself.execution_count) |
|
181 | ||
179 | except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError): |
|
182 | try: | |
180 | # Case 1 |
|
183 | code_ast = ast.parse(cell, filename=cell_name) | |
181 | ipself.showsyntaxerror(filename) |
|
184 | except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError): | |
182 | return None |
|
185 | # Case 1 | |
183 |
|
186 | ipself.showsyntaxerror() | ||
184 | if code is None: |
|
187 | ipself.execution_count += 1 | |
185 |
|
|
188 | return None | |
186 | return True |
|
189 | except NameError: | |
187 |
|
190 | pass | ||
188 | # Case 3 |
|
191 | ||
189 | # Because autopx is enabled, we now call executeAll or disable autopx if |
|
192 | if store_history: | |
190 | # %autopx or autopx has been called |
|
193 | # Write output to the database. Does nothing unless | |
191 | if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source: |
|
194 | # history output logging is enabled. | |
|
195 | ipself.history_manager.store_output(ipself.execution_count) | |||
|
196 | # Each cell is a *single* input, regardless of how many lines it has | |||
|
197 | ipself.execution_count += 1 | |||
|
198 | print cell | |||
|
199 | ||||
|
200 | if re.search(r'get_ipython\(\)\.magic\(u?"%?autopx', cell): | |||
192 | self._disable_autopx() |
|
201 | self._disable_autopx() | |
193 | return False |
|
202 | return False | |
194 | else: |
|
203 | else: | |
195 | try: |
|
204 | try: | |
196 |
result = self.active_ |
|
205 | result = self.active_view.execute(cell, block=False) | |
197 | except: |
|
206 | except: | |
198 | ipself.showtraceback() |
|
207 | ipself.showtraceback() | |
199 |
else |
|
208 | return False | |
200 | print result.__repr__() |
|
209 | ||
|
210 | if self.active_view.block: | |||
|
211 | try: | |||
|
212 | result.get() | |||
|
213 | except: | |||
|
214 | ipself.showtraceback() | |||
|
215 | else: | |||
|
216 | targets = self.active_view.targets | |||
|
217 | if isinstance(targets, int): | |||
|
218 | targets = [targets] | |||
|
219 | if targets == 'all': | |||
|
220 | targets = self.active_view.client.ids | |||
|
221 | stdout = [s.rstrip() for s in result.stdout] | |||
|
222 | if any(stdout): | |||
|
223 | for i,eid in enumerate(targets): | |||
|
224 | print '[stdout:%i]'%eid, stdout[i] | |||
201 | return False |
|
225 | return False | |
202 |
|
226 | |||
203 |
|
227 |
@@ -648,7 +648,7 b' class DirectView(View):' | |||||
648 | # block = block if block is not None else self.block |
|
648 | # block = block if block is not None else self.block | |
649 | return self.pull(key_s, block=True) |
|
649 | return self.pull(key_s, block=True) | |
650 |
|
650 | |||
651 |
def pull(self, names, targets=None, block= |
|
651 | def pull(self, names, targets=None, block=None): | |
652 | """get object(s) by `name` from remote namespace |
|
652 | """get object(s) by `name` from remote namespace | |
653 |
|
653 | |||
654 | will return one object if it is a key. |
|
654 | will return one object if it is a key. | |
@@ -766,7 +766,7 b' class DirectView(View):' | |||||
766 | else: |
|
766 | else: | |
767 | pmagic = ip.plugin_manager.get_plugin('parallelmagic') |
|
767 | pmagic = ip.plugin_manager.get_plugin('parallelmagic') | |
768 | if pmagic is not None: |
|
768 | if pmagic is not None: | |
769 |
pmagic.active_ |
|
769 | pmagic.active_view = self | |
770 | else: |
|
770 | else: | |
771 | print "You must first load the parallelmagic extension " \ |
|
771 | print "You must first load the parallelmagic extension " \ | |
772 | "by doing '%load_ext parallelmagic'" |
|
772 | "by doing '%load_ext parallelmagic'" |
General Comments 0
You need to be logged in to leave comments.
Login now