Show More
@@ -32,6 +32,7 b' import zmq' | |||
|
32 | 32 | |
|
33 | 33 | from IPython.config.configurable import MultipleInstanceError |
|
34 | 34 | from IPython.core.application import BaseIPythonApplication |
|
35 | from IPython.core.profiledir import ProfileDir, ProfileDirError | |
|
35 | 36 | |
|
36 | 37 | from IPython.utils.coloransi import TermColors |
|
37 | 38 | from IPython.utils.jsonutil import rekey |
@@ -50,7 +51,6 b' from IPython.parallel import util' | |||
|
50 | 51 | from IPython.zmq.session import Session, Message |
|
51 | 52 | |
|
52 | 53 | from .asyncresult import AsyncResult, AsyncHubResult |
|
53 | from IPython.core.profiledir import ProfileDir, ProfileDirError | |
|
54 | 54 | from .view import DirectView, LoadBalancedView |
|
55 | 55 | |
|
56 | 56 | if sys.version_info[0] >= 3: |
@@ -480,6 +480,18 b' class Client(HasTraits):' | |||
|
480 | 480 | self._queue_handlers = {'execute_reply' : self._handle_execute_reply, |
|
481 | 481 | 'apply_reply' : self._handle_apply_reply} |
|
482 | 482 | self._connect(sshserver, ssh_kwargs, timeout) |
|
483 | ||
|
484 | # last step: setup magics, if we are in IPython: | |
|
485 | ||
|
486 | try: | |
|
487 | ip = get_ipython() | |
|
488 | except NameError: | |
|
489 | return | |
|
490 | else: | |
|
491 | if 'px' not in ip.magics_manager.magics: | |
|
492 | # in IPython but we are the first Client. | |
|
493 | # activate a default view for parallel magics. | |
|
494 | self.activate() | |
|
483 | 495 | |
|
484 | 496 | def __del__(self): |
|
485 | 497 | """cleanup sockets, but _not_ context.""" |
@@ -905,6 +917,29 b' class Client(HasTraits):' | |||
|
905 | 917 | # always copy: |
|
906 | 918 | return list(self._ids) |
|
907 | 919 | |
|
920 | def activate(self, targets='all', suffix=''): | |
|
921 | """Create a DirectView and register it with IPython magics | |
|
922 | ||
|
923 | Defines the magics `%px, %autopx, %pxresult, %%px` | |
|
924 | ||
|
925 | Parameters | |
|
926 | ---------- | |
|
927 | ||
|
928 | targets: int, list of ints, or 'all' | |
|
929 | The engines on which the view's magics will run | |
|
930 | suffix: str [default: ''] | |
|
931 | The suffix, if any, for the magics. This allows you to have | |
|
932 | multiple views associated with parallel magics at the same time. | |
|
933 | ||
|
934 | e.g. ``rc.activate(targets=0, suffix='0')`` will give you | |
|
935 | the magics ``%px0``, ``%pxresult0``, etc. for running magics just | |
|
936 | on engine 0. | |
|
937 | """ | |
|
938 | view = self.direct_view(targets) | |
|
939 | view.block = True | |
|
940 | view.activate(suffix) | |
|
941 | return view | |
|
942 | ||
|
908 | 943 | def close(self): |
|
909 | 944 | if self._closed: |
|
910 | 945 | return |
@@ -17,10 +17,14 b' Usage' | |||
|
17 | 17 | |
|
18 | 18 | {PX_DOC} |
|
19 | 19 | |
|
20 | ``%result`` | |
|
20 | ``%pxresult`` | |
|
21 | 21 | |
|
22 | 22 | {RESULT_DOC} |
|
23 | 23 | |
|
24 | ``%pxconfig`` | |
|
25 | ||
|
26 | {CONFIG_DOC} | |
|
27 | ||
|
24 | 28 | """ |
|
25 | 29 | |
|
26 | 30 | #----------------------------------------------------------------------------- |
@@ -38,7 +42,8 b' import ast' | |||
|
38 | 42 | import re |
|
39 | 43 | |
|
40 | 44 | from IPython.core.error import UsageError |
|
41 |
from IPython.core.magic import Magics |
|
|
45 | from IPython.core.magic import Magics | |
|
46 | from IPython.core import magic_arguments | |
|
42 | 47 | from IPython.testing.skipdoctest import skip_doctest |
|
43 | 48 | |
|
44 | 49 | #----------------------------------------------------------------------------- |
@@ -46,95 +51,164 b' from IPython.testing.skipdoctest import skip_doctest' | |||
|
46 | 51 | #----------------------------------------------------------------------------- |
|
47 | 52 | |
|
48 | 53 | |
|
49 | NO_ACTIVE_VIEW = "Use activate() on a DirectView object to use it with magics." | |
|
50 | NO_LAST_RESULT = "%result recalls last %px result, which has not yet been used." | |
|
54 | NO_LAST_RESULT = "%pxresult recalls last %px result, which has not yet been used." | |
|
51 | 55 | |
|
56 | def exec_args(f): | |
|
57 | """decorator for adding block/targets args for execution | |
|
58 | ||
|
59 | applied to %pxconfig and %%px | |
|
60 | """ | |
|
61 | args = [ | |
|
62 | magic_arguments.argument('-b', '--block', action="store_const", | |
|
63 | const=True, dest='block', | |
|
64 | help="use blocking (sync) execution" | |
|
65 | ), | |
|
66 | magic_arguments.argument('-a', '--noblock', action="store_const", | |
|
67 | const=False, dest='block', | |
|
68 | help="use non-blocking (async) execution" | |
|
69 | ), | |
|
70 | magic_arguments.argument('-t', '--targets', type=str, | |
|
71 | help="specify the targets on which to execute" | |
|
72 | ), | |
|
73 | ] | |
|
74 | for a in args: | |
|
75 | f = a(f) | |
|
76 | return f | |
|
77 | ||
|
78 | def output_args(f): | |
|
79 | """decorator for output-formatting args | |
|
80 | ||
|
81 | applied to %pxresult and %%px | |
|
82 | """ | |
|
83 | args = [ | |
|
84 | magic_arguments.argument('-r', action="store_const", dest='groupby', | |
|
85 | const='order', | |
|
86 | help="collate outputs in order (same as group-outputs=order)" | |
|
87 | ), | |
|
88 | magic_arguments.argument('-e', action="store_const", dest='groupby', | |
|
89 | const='engine', | |
|
90 | help="group outputs by engine (same as group-outputs=engine)" | |
|
91 | ), | |
|
92 | magic_arguments.argument('--group-outputs', dest='groupby', type=str, | |
|
93 | choices=['engine', 'order', 'type'], default='type', | |
|
94 | help="""Group the outputs in a particular way. | |
|
95 | ||
|
96 | Choices are: | |
|
97 | ||
|
98 | type: group outputs of all engines by type (stdout, stderr, displaypub, etc.). | |
|
99 | ||
|
100 | engine: display all output for each engine together. | |
|
101 | ||
|
102 | order: like type, but individual displaypub output from each engine is collated. | |
|
103 | For example, if multiple plots are generated by each engine, the first | |
|
104 | figure of each engine will be displayed, then the second of each, etc. | |
|
105 | """ | |
|
106 | ), | |
|
107 | magic_arguments.argument('-o', '--out', dest='save_name', type=str, | |
|
108 | help="""store the AsyncResult object for this computation | |
|
109 | in the global namespace under this name. | |
|
110 | """ | |
|
111 | ), | |
|
112 | ] | |
|
113 | for a in args: | |
|
114 | f = a(f) | |
|
115 | return f | |
|
52 | 116 | |
|
53 | @magics_class | |
|
54 | 117 | class ParallelMagics(Magics): |
|
55 | 118 | """A set of magics useful when controlling a parallel IPython cluster. |
|
56 | 119 | """ |
|
57 | 120 | |
|
121 | # magic-related | |
|
122 | magics = None | |
|
123 | registered = True | |
|
124 | ||
|
125 | # suffix for magics | |
|
126 | suffix = '' | |
|
58 | 127 | # A flag showing if autopx is activated or not |
|
59 | 128 | _autopx = False |
|
60 | 129 | # the current view used by the magics: |
|
61 |
|
|
|
62 | # last result cache for %result | |
|
130 | view = None | |
|
131 | # last result cache for %pxresult | |
|
63 | 132 | last_result = None |
|
64 | 133 | |
|
65 | @skip_doctest | |
|
66 | @line_magic | |
|
67 | def result(self, line=''): | |
|
68 | """Print the result of the last asynchronous %px command. | |
|
69 | ||
|
70 | Usage: | |
|
134 | def __init__(self, shell, view, suffix=''): | |
|
135 | self.view = view | |
|
136 | self.suffix = suffix | |
|
71 | 137 | |
|
72 | %result [-o] [-e] [--group-options=type|engine|order] | |
|
138 | # register magics | |
|
139 | self.magics = dict(cell={},line={}) | |
|
140 | line_magics = self.magics['line'] | |
|
73 | 141 | |
|
74 | Options: | |
|
142 | px = 'px' + suffix | |
|
143 | if not suffix: | |
|
144 | # keep %result for legacy compatibility | |
|
145 | line_magics['result'] = self.result | |
|
75 | 146 | |
|
76 | -o: collate outputs in order (same as group-outputs=order) | |
|
147 | line_magics['pxresult' + suffix] = self.result | |
|
148 | line_magics[px] = self.px | |
|
149 | line_magics['pxconfig' + suffix] = self.pxconfig | |
|
150 | line_magics['auto' + px] = self.autopx | |
|
77 | 151 | |
|
78 | -e: group outputs by engine (same as group-outputs=engine) | |
|
152 | self.magics['cell'][px] = self.cell_px | |
|
79 | 153 | |
|
80 | --group-outputs=type [default behavior]: | |
|
81 | each output type (stdout, stderr, displaypub) for all engines | |
|
82 | displayed together. | |
|
83 | ||
|
84 | --group-outputs=order: | |
|
85 | The same as 'type', but individual displaypub outputs (e.g. plots) | |
|
86 | will be interleaved, so it will display all of the first plots, | |
|
87 | then all of the second plots, etc. | |
|
88 | ||
|
89 | --group-outputs=engine: | |
|
90 | All of an engine's output is displayed before moving on to the next. | |
|
91 | ||
|
92 | To use this a :class:`DirectView` instance must be created | |
|
93 | and then activated by calling its :meth:`activate` method. | |
|
154 | super(ParallelMagics, self).__init__(shell=shell) | |
|
155 | ||
|
156 | def _eval_target_str(self, ts): | |
|
157 | if ':' in ts: | |
|
158 | targets = eval("self.view.client.ids[%s]" % ts) | |
|
159 | elif 'all' in ts: | |
|
160 | targets = 'all' | |
|
161 | else: | |
|
162 | targets = eval(ts) | |
|
163 | return targets | |
|
164 | ||
|
165 | @magic_arguments.magic_arguments() | |
|
166 | @exec_args | |
|
167 | def pxconfig(self, line): | |
|
168 | """configure default targets/blocking for %px magics""" | |
|
169 | args = magic_arguments.parse_argstring(self.pxconfig, line) | |
|
170 | if args.targets: | |
|
171 | self.view.targets = self._eval_target_str(args.targets) | |
|
172 | if args.block is not None: | |
|
173 | self.view.block = args.block | |
|
174 | ||
|
175 | @magic_arguments.magic_arguments() | |
|
176 | @output_args | |
|
177 | @skip_doctest | |
|
178 | def result(self, line=''): | |
|
179 | """Print the result of the last asynchronous %px command. | |
|
94 | 180 | |
|
95 | 181 | This lets you recall the results of %px computations after |
|
96 |
asynchronous submission ( |
|
|
182 | asynchronous submission (block=False). | |
|
97 | 183 | |
|
98 | Then you can do the following:: | |
|
184 | Examples | |
|
185 | -------- | |
|
186 | :: | |
|
99 | 187 | |
|
100 | 188 | In [23]: %px os.getpid() |
|
101 | 189 | Async parallel execution on engine(s): all |
|
102 | 190 | |
|
103 | In [24]: %result | |
|
191 | In [24]: %pxresult | |
|
104 | 192 | [ 8] Out[10]: 60920 |
|
105 | 193 | [ 9] Out[10]: 60921 |
|
106 | 194 | [10] Out[10]: 60922 |
|
107 | 195 | [11] Out[10]: 60923 |
|
108 | 196 | """ |
|
109 | opts, _ = self.parse_options(line, 'oe', 'group-outputs=') | |
|
110 | ||
|
111 | if 'group-outputs' in opts: | |
|
112 | groupby = opts['group-outputs'] | |
|
113 | elif 'o' in opts: | |
|
114 | groupby = 'order' | |
|
115 | elif 'e' in opts: | |
|
116 | groupby = 'engine' | |
|
117 | else: | |
|
118 | groupby = 'type' | |
|
119 | ||
|
120 | if self.active_view is None: | |
|
121 | raise UsageError(NO_ACTIVE_VIEW) | |
|
197 | args = magic_arguments.parse_argstring(self.result, line) | |
|
122 | 198 | |
|
123 | 199 | if self.last_result is None: |
|
124 | 200 | raise UsageError(NO_LAST_RESULT) |
|
125 | 201 | |
|
126 | 202 | self.last_result.get() |
|
127 | self.last_result.display_outputs(groupby=groupby) | |
|
203 | self.last_result.display_outputs(groupby=args.groupby) | |
|
128 | 204 | |
|
129 | 205 | @skip_doctest |
|
130 | @line_magic | |
|
131 | def px(self, parameter_s=''): | |
|
206 | def px(self, line=''): | |
|
132 | 207 | """Executes the given python command in parallel. |
|
133 | 208 | |
|
134 | To use this a :class:`DirectView` instance must be created | |
|
135 | and then activated by calling its :meth:`activate` method. | |
|
136 | ||
|
137 | Then you can do the following:: | |
|
209 | Examples | |
|
210 | -------- | |
|
211 | :: | |
|
138 | 212 | |
|
139 | 213 | In [24]: %px a = os.getpid() |
|
140 | 214 | Parallel execution on engine(s): all |
@@ -145,27 +219,24 b' class ParallelMagics(Magics):' | |||
|
145 | 219 | [stdout:2] 1236 |
|
146 | 220 | [stdout:3] 1237 |
|
147 | 221 | """ |
|
148 |
return self.parallel_execute( |
|
|
222 | return self.parallel_execute(line) | |
|
149 | 223 | |
|
150 | 224 | def parallel_execute(self, cell, block=None, groupby='type', save_name=None): |
|
151 | 225 | """implementation used by %px and %%parallel""" |
|
152 | 226 | |
|
153 | if self.active_view is None: | |
|
154 | raise UsageError(NO_ACTIVE_VIEW) | |
|
155 | ||
|
156 | 227 | # defaults: |
|
157 |
block = self. |
|
|
228 | block = self.view.block if block is None else block | |
|
158 | 229 | |
|
159 | 230 | base = "Parallel" if block else "Async parallel" |
|
160 | 231 | |
|
161 |
targets = self. |
|
|
232 | targets = self.view.targets | |
|
162 | 233 | if isinstance(targets, list) and len(targets) > 10: |
|
163 | 234 | str_targets = str(targets[:4])[:-1] + ', ..., ' + str(targets[-4:])[1:] |
|
164 | 235 | else: |
|
165 | 236 | str_targets = str(targets) |
|
166 | 237 | print base + " execution on engine(s): %s" % str_targets |
|
167 | 238 | |
|
168 |
result = self. |
|
|
239 | result = self.view.execute(cell, silent=False, block=False) | |
|
169 | 240 | self.last_result = result |
|
170 | 241 | |
|
171 | 242 | if save_name: |
@@ -178,45 +249,16 b' class ParallelMagics(Magics):' | |||
|
178 | 249 | # return AsyncResult only on non-blocking submission |
|
179 | 250 | return result |
|
180 | 251 | |
|
252 | @magic_arguments.magic_arguments() | |
|
253 | @exec_args | |
|
254 | @output_args | |
|
181 | 255 | @skip_doctest |
|
182 | @cell_magic('px') | |
|
183 | 256 | def cell_px(self, line='', cell=None): |
|
184 |
"""Executes the |
|
|
185 | ||
|
186 | Cell magic usage: | |
|
187 | ||
|
188 | %%px [-o] [-e] [--group-options=type|engine|order] [--[no]block] [--out name] | |
|
189 | ||
|
190 | Options: | |
|
191 | ||
|
192 | --out <name>: store the AsyncResult object for this computation | |
|
193 | in the global namespace. | |
|
194 | ||
|
195 | -o: collate outputs in order (same as group-outputs=order) | |
|
196 | ||
|
197 | -e: group outputs by engine (same as group-outputs=engine) | |
|
198 | ||
|
199 | --group-outputs=type [default behavior]: | |
|
200 | each output type (stdout, stderr, displaypub) for all engines | |
|
201 | displayed together. | |
|
202 | ||
|
203 | --group-outputs=order: | |
|
204 | The same as 'type', but individual displaypub outputs (e.g. plots) | |
|
205 | will be interleaved, so it will display all of the first plots, | |
|
206 | then all of the second plots, etc. | |
|
207 | ||
|
208 | --group-outputs=engine: | |
|
209 | All of an engine's output is displayed before moving on to the next. | |
|
210 | ||
|
211 | --[no]block: | |
|
212 | Whether or not to block for the execution to complete | |
|
213 | (and display the results). If unspecified, the active view's | |
|
257 | """Executes the cell in parallel. | |
|
214 | 258 | |
|
215 | ||
|
216 | To use this a :class:`DirectView` instance must be created | |
|
217 | and then activated by calling its :meth:`activate` method. | |
|
218 | ||
|
219 | Then you can do the following:: | |
|
259 | Examples | |
|
260 | -------- | |
|
261 | :: | |
|
220 | 262 | |
|
221 | 263 | In [24]: %%px --noblock |
|
222 | 264 | ....: a = os.getpid() |
@@ -230,38 +272,29 b' class ParallelMagics(Magics):' | |||
|
230 | 272 | [stdout:3] 1237 |
|
231 | 273 | """ |
|
232 | 274 | |
|
233 | block = None | |
|
234 | groupby = 'type' | |
|
235 | # as a cell magic, we accept args | |
|
236 | opts, _ = self.parse_options(line, 'oe', 'group-outputs=', 'out=', 'block', 'noblock') | |
|
237 | ||
|
238 | if 'group-outputs' in opts: | |
|
239 | groupby = opts['group-outputs'] | |
|
240 | elif 'o' in opts: | |
|
241 | groupby = 'order' | |
|
242 | elif 'e' in opts: | |
|
243 | groupby = 'engine' | |
|
244 | ||
|
245 | if 'block' in opts: | |
|
246 | block = True | |
|
247 | elif 'noblock' in opts: | |
|
248 | block = False | |
|
249 | ||
|
250 | save_name = opts.get('out') | |
|
251 | ||
|
252 | return self.parallel_execute(cell, block=block, groupby=groupby, save_name=save_name) | |
|
253 | ||
|
275 | args = magic_arguments.parse_argstring(self.cell_px, line) | |
|
276 | ||
|
277 | if args.targets: | |
|
278 | save_targets = self.view.targets | |
|
279 | self.view.targets = self._eval_target_str(args.targets) | |
|
280 | try: | |
|
281 | return self.parallel_execute(cell, block=args.block, | |
|
282 | groupby=args.groupby, | |
|
283 | save_name=args.save_name, | |
|
284 | ) | |
|
285 | finally: | |
|
286 | if args.targets: | |
|
287 | self.view.targets = save_targets | |
|
288 | ||
|
254 | 289 | @skip_doctest |
|
255 | @line_magic | |
|
256 | def autopx(self, parameter_s=''): | |
|
290 | def autopx(self, line=''): | |
|
257 | 291 | """Toggles auto parallel mode. |
|
258 | 292 | |
|
259 | To use this a :class:`DirectView` instance must be created | |
|
260 | and then activated by calling its :meth:`activate` method. Once this | |
|
261 | is called, all commands typed at the command line are send to | |
|
262 | the engines to be executed in parallel. To control which engine | |
|
263 | are used, set the ``targets`` attributed of the multiengine client | |
|
264 | before entering ``%autopx`` mode. | |
|
293 | Once this is called, all commands typed at the command line are send to | |
|
294 | the engines to be executed in parallel. To control which engine are | |
|
295 | used, the ``targets`` attribute of the view before | |
|
296 | entering ``%autopx`` mode. | |
|
297 | ||
|
265 | 298 | |
|
266 | 299 | Then you can do the following:: |
|
267 | 300 | |
@@ -290,9 +323,6 b' class ParallelMagics(Magics):' | |||
|
290 | 323 | """Enable %autopx mode by saving the original run_cell and installing |
|
291 | 324 | pxrun_cell. |
|
292 | 325 | """ |
|
293 | if self.active_view is None: | |
|
294 | raise UsageError(NO_ACTIVE_VIEW) | |
|
295 | ||
|
296 | 326 | # override run_cell |
|
297 | 327 | self._original_run_cell = self.shell.run_cell |
|
298 | 328 | self.shell.run_cell = self.pxrun_cell |
@@ -356,12 +386,12 b' class ParallelMagics(Magics):' | |||
|
356 | 386 | return False |
|
357 | 387 | else: |
|
358 | 388 | try: |
|
359 |
result = self. |
|
|
389 | result = self.view.execute(cell, silent=False, block=False) | |
|
360 | 390 | except: |
|
361 | 391 | ipself.showtraceback() |
|
362 | 392 | return True |
|
363 | 393 | else: |
|
364 |
if self. |
|
|
394 | if self.view.block: | |
|
365 | 395 | try: |
|
366 | 396 | result.get() |
|
367 | 397 | except: |
@@ -376,15 +406,6 b' class ParallelMagics(Magics):' | |||
|
376 | 406 | __doc__ = __doc__.format( |
|
377 | 407 | AUTOPX_DOC = ' '*8 + ParallelMagics.autopx.__doc__, |
|
378 | 408 | PX_DOC = ' '*8 + ParallelMagics.px.__doc__, |
|
379 | RESULT_DOC = ' '*8 + ParallelMagics.result.__doc__ | |
|
409 | RESULT_DOC = ' '*8 + ParallelMagics.result.__doc__, | |
|
410 | CONFIG_DOC = ' '*8 + ParallelMagics.pxconfig.__doc__, | |
|
380 | 411 | ) |
|
381 | ||
|
382 | _loaded = False | |
|
383 | ||
|
384 | ||
|
385 | def load_ipython_extension(ip): | |
|
386 | """Load the extension in IPython.""" | |
|
387 | global _loaded | |
|
388 | if not _loaded: | |
|
389 | ip.register_magics(ParallelMagics) | |
|
390 | _loaded = True |
@@ -792,33 +792,37 b' class DirectView(View):' | |||
|
792 | 792 | return self.client.kill(targets=targets, block=block) |
|
793 | 793 | |
|
794 | 794 | #---------------------------------------- |
|
795 | # activate for %px,%autopx magics | |
|
795 | # activate for %px, %autopx, etc. magics | |
|
796 | 796 | #---------------------------------------- |
|
797 | def activate(self): | |
|
798 | """Make this `View` active for parallel magic commands. | |
|
799 | 797 | |
|
800 | IPython has a magic command syntax to work with `MultiEngineClient` objects. | |
|
801 | In a given IPython session there is a single active one. While | |
|
802 | there can be many `Views` created and used by the user, | |
|
803 | there is only one active one. The active `View` is used whenever | |
|
804 | the magic commands %px and %autopx are used. | |
|
805 | ||
|
806 | The activate() method is called on a given `View` to make it | |
|
807 | active. Once this has been done, the magic commands can be used. | |
|
798 | def activate(self, suffix=''): | |
|
799 | """Activate IPython magics associated with this View | |
|
800 | ||
|
801 | Defines the magics `%px, %autopx, %pxresult, %%px, %pxconfig` | |
|
802 | ||
|
803 | Parameters | |
|
804 | ---------- | |
|
805 | ||
|
806 | suffix: str [default: ''] | |
|
807 | The suffix, if any, for the magics. This allows you to have | |
|
808 | multiple views associated with parallel magics at the same time. | |
|
809 | ||
|
810 | e.g. ``rc[::2].activate(suffix='_even')`` will give you | |
|
811 | the magics ``%px_even``, ``%pxresult_even``, etc. for running magics | |
|
812 | on the even engines. | |
|
808 | 813 | """ |
|
809 | ||
|
814 | ||
|
815 | from IPython.parallel.client.magics import ParallelMagics | |
|
816 | ||
|
810 | 817 | try: |
|
811 | 818 | # This is injected into __builtins__. |
|
812 | 819 | ip = get_ipython() |
|
813 | 820 | except NameError: |
|
814 |
print "The IPython parallel magics ( |
|
|
815 | else: | |
|
816 | pmagic = ip.magics_manager.registry.get('ParallelMagics') | |
|
817 | if pmagic is None: | |
|
818 | ip.magic('load_ext parallelmagic') | |
|
819 | pmagic = ip.magics_manager.registry.get('ParallelMagics') | |
|
820 | ||
|
821 | pmagic.active_view = self | |
|
821 | print "The IPython parallel magics (%px, etc.) only work within IPython." | |
|
822 | return | |
|
823 | ||
|
824 | M = ParallelMagics(ip, self, suffix) | |
|
825 | ip.magics_manager.register(M) | |
|
822 | 826 | |
|
823 | 827 | |
|
824 | 828 | @skip_doctest |
@@ -24,6 +24,7 b' from tempfile import mktemp' | |||
|
24 | 24 | |
|
25 | 25 | import zmq |
|
26 | 26 | |
|
27 | from IPython import parallel | |
|
27 | 28 | from IPython.parallel.client import client as clientmod |
|
28 | 29 | from IPython.parallel import error |
|
29 | 30 | from IPython.parallel import AsyncResult, AsyncHubResult |
@@ -420,3 +421,16 b' class TestClient(ClusterTestCase):' | |||
|
420 | 421 | "Shouldn't be spinning, but got wall_time=%f" % ar.wall_time |
|
421 | 422 | ) |
|
422 | 423 | |
|
424 | def test_activate(self): | |
|
425 | ip = get_ipython() | |
|
426 | magics = ip.magics_manager.magics | |
|
427 | self.assertTrue('px' in magics['line']) | |
|
428 | self.assertTrue('px' in magics['cell']) | |
|
429 | v0 = self.client.activate(-1, '0') | |
|
430 | self.assertTrue('px0' in magics['line']) | |
|
431 | self.assertTrue('px0' in magics['cell']) | |
|
432 | self.assertEquals(v0.targets, self.client.ids[-1]) | |
|
433 | v0 = self.client.activate('all', 'all') | |
|
434 | self.assertTrue('pxall' in magics['line']) | |
|
435 | self.assertTrue('pxall' in magics['cell']) | |
|
436 | self.assertEquals(v0.targets, 'all') |
@@ -301,20 +301,13 b' class TestParallelMagics(ClusterTestCase, ParametricTestCase):' | |||
|
301 | 301 | data = dict(a=111,b=222) |
|
302 | 302 | v.push(data, block=True) |
|
303 | 303 | |
|
304 | ip.magic('px a') | |
|
305 |
ip.magic('px |
|
|
306 | for idx, name in [ | |
|
307 | ('', 'b'), | |
|
308 | ('-1', 'b'), | |
|
309 | ('2', 'b'), | |
|
310 | ('1', 'a'), | |
|
311 | ('-2', 'a'), | |
|
312 | ]: | |
|
304 | for name in ('a', 'b'): | |
|
305 | ip.magic('px ' + name) | |
|
313 | 306 | with capture_output() as io: |
|
314 |
ip.magic('result |
|
|
307 | ip.magic('pxresult') | |
|
315 | 308 | output = io.stdout |
|
316 | 309 | msg = "expected %s output to include %s, but got: %s" % \ |
|
317 |
('%result |
|
|
310 | ('%pxresult', str(data[name]), output) | |
|
318 | 311 | self.assertTrue(str(data[name]) in output, msg) |
|
319 | 312 | |
|
320 | 313 | @dec.skipif_not_matplotlib |
@@ -336,5 +329,17 b' class TestParallelMagics(ClusterTestCase, ParametricTestCase):' | |||
|
336 | 329 | |
|
337 | 330 | self.assertTrue('Out[' in io.stdout, io.stdout) |
|
338 | 331 | self.assertTrue('matplotlib.lines' in io.stdout, io.stdout) |
|
332 | ||
|
333 | def test_pxconfig(self): | |
|
334 | ip = get_ipython() | |
|
335 | rc = self.client | |
|
336 | v = rc.activate(-1, '_tst') | |
|
337 | self.assertEquals(v.targets, rc.ids[-1]) | |
|
338 | ip.magic("%pxconfig_tst -t :") | |
|
339 | self.assertEquals(v.targets, rc.ids) | |
|
340 | ip.magic("%pxconfig_tst --block") | |
|
341 | self.assertEquals(v.block, True) | |
|
342 | ip.magic("%pxconfig_tst --noblock") | |
|
343 | self.assertEquals(v.block, False) | |
|
339 | 344 | |
|
340 | 345 |
General Comments 0
You need to be logged in to leave comments.
Login now