##// END OF EJS Templates
add tests for parallel magics...
MinRK -
Show More
@@ -1,276 +1,290 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 """Magic command interface for interactive parallel work."""
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2009 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import ast
18 18 import re
19 19
20 20 from IPython.core.plugin import Plugin
21 21 from IPython.utils.traitlets import Bool, Any, Instance
22 22 from IPython.testing import decorators as testdec
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Definitions of magic functions for use with IPython
26 26 #-----------------------------------------------------------------------------
27 27
28 28
29 29 NO_ACTIVE_VIEW = """
30 30 Use activate() on a DirectView object to activate it for magics.
31 31 """
32 32
33 33
34 34 class ParalleMagic(Plugin):
35 35 """A component to manage the %result, %px and %autopx magics."""
36 36
37 active_view = Any()
37 active_view = Instance('IPython.parallel.client.view.DirectView')
38 38 verbose = Bool(False, config=True)
39 39 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
40 40
41 41 def __init__(self, shell=None, config=None):
42 42 super(ParalleMagic, self).__init__(shell=shell, config=config)
43 43 self._define_magics()
44 44 # A flag showing if autopx is activated or not
45 45 self.autopx = False
46 46
47 47 def _define_magics(self):
48 48 """Define the magic functions."""
49 49 self.shell.define_magic('result', self.magic_result)
50 50 self.shell.define_magic('px', self.magic_px)
51 51 self.shell.define_magic('autopx', self.magic_autopx)
52 52
53 53 @testdec.skip_doctest
54 54 def magic_result(self, ipself, parameter_s=''):
55 55 """Print the result of command i on all engines..
56 56
57 57 To use this a :class:`DirectView` instance must be created
58 58 and then activated by calling its :meth:`activate` method.
59 59
60 60 Then you can do the following::
61 61
62 62 In [23]: %result
63 63 Out[23]:
64 64 <Results List>
65 65 [0] In [6]: a = 10
66 66 [1] In [6]: a = 10
67 67
68 68 In [22]: %result 6
69 69 Out[22]:
70 70 <Results List>
71 71 [0] In [6]: a = 10
72 72 [1] In [6]: a = 10
73 73 """
74 74 if self.active_view is None:
75 75 print NO_ACTIVE_VIEW
76 76 return
77 77
78 78 try:
79 79 index = int(parameter_s)
80 80 except:
81 81 index = None
82 82 result = self.active_view.get_result(index)
83 83 return result
84 84
85 85 @testdec.skip_doctest
86 86 def magic_px(self, ipself, parameter_s=''):
87 87 """Executes the given python command in parallel.
88 88
89 89 To use this a :class:`DirectView` instance must be created
90 90 and then activated by calling its :meth:`activate` method.
91 91
92 92 Then you can do the following::
93 93
94 94 In [24]: %px a = 5
95 95 Parallel execution on engines: all
96 96 Out[24]:
97 97 <Results List>
98 98 [0] In [7]: a = 5
99 99 [1] In [7]: a = 5
100 100 """
101 101
102 102 if self.active_view is None:
103 103 print NO_ACTIVE_VIEW
104 104 return
105 105 print "Parallel execution on engines: %s" % self.active_view.targets
106 result = self.active_view.execute(parameter_s)
107 return result
106 result = self.active_view.execute(parameter_s, block=False)
107 if self.active_view.block:
108 result.get()
109 self._maybe_display_output(result)
108 110
109 111 @testdec.skip_doctest
110 112 def magic_autopx(self, ipself, parameter_s=''):
111 113 """Toggles auto parallel mode.
112 114
113 115 To use this a :class:`DirectView` instance must be created
114 116 and then activated by calling its :meth:`activate` method. Once this
115 117 is called, all commands typed at the command line are send to
116 118 the engines to be executed in parallel. To control which engine
117 119 are used, set the ``targets`` attributed of the multiengine client
118 120 before entering ``%autopx`` mode.
119 121
120 122 Then you can do the following::
121 123
122 124 In [25]: %autopx
123 125 %autopx to enabled
124 126
125 127 In [26]: a = 10
126 <Results List>
127 [0] In [8]: a = 10
128 [1] In [8]: a = 10
128 Parallel execution on engines: [0,1,2,3]
129 In [27]: print a
130 Parallel execution on engines: [0,1,2,3]
131 [stdout:0] 10
132 [stdout:1] 10
133 [stdout:2] 10
134 [stdout:3] 10
129 135
130 136
131 137 In [27]: %autopx
132 138 %autopx disabled
133 139 """
134 140 if self.autopx:
135 141 self._disable_autopx()
136 142 else:
137 143 self._enable_autopx()
138 144
139 145 def _enable_autopx(self):
140 146 """Enable %autopx mode by saving the original run_cell and installing
141 147 pxrun_cell.
142 148 """
143 149 if self.active_view is None:
144 150 print NO_ACTIVE_VIEW
145 151 return
146 152
147 153 # override run_cell and run_code
148 154 self._original_run_cell = self.shell.run_cell
149 155 self.shell.run_cell = self.pxrun_cell
150 156 self._original_run_code = self.shell.run_code
151 157 self.shell.run_code = self.pxrun_code
152 158
153 159 self.autopx = True
154 160 print "%autopx enabled"
155 161
156 162 def _disable_autopx(self):
157 163 """Disable %autopx by restoring the original InteractiveShell.run_cell.
158 164 """
159 165 if self.autopx:
160 166 self.shell.run_cell = self._original_run_cell
161 167 self.shell.run_code = self._original_run_code
162 168 self.autopx = False
163 169 print "%autopx disabled"
164 170
165 171 def _maybe_display_output(self, result):
166 172 """Maybe display the output of a parallel result.
167 173
168 174 If self.active_view.block is True, wait for the result
169 175 and display the result. Otherwise, this is a noop.
170 176 """
171 if self.active_view.block:
172 try:
173 result.get()
174 except:
175 self.shell.showtraceback()
176 return True
177 else:
178 targets = self.active_view.targets
179 if isinstance(targets, int):
180 targets = [targets]
181 if targets == 'all':
182 targets = self.active_view.client.ids
183 stdout = [s.rstrip() for s in result.stdout]
184 if any(stdout):
185 for i,eid in enumerate(targets):
186 print '[stdout:%i]'%eid, stdout[i]
187 return False
177 targets = self.active_view.targets
178 if isinstance(targets, int):
179 targets = [targets]
180 if targets == 'all':
181 targets = self.active_view.client.ids
182 stdout = [s.rstrip() for s in result.stdout]
183 if any(stdout):
184 for i,eid in enumerate(targets):
185 print '[stdout:%i]'%eid, stdout[i]
188 186
189 187
190 188 def pxrun_cell(self, cell, store_history=True):
191 189 """drop-in replacement for InteractiveShell.run_cell.
192 190
193 191 This executes code remotely, instead of in the local namespace.
194 192
195 193 See InteractiveShell.run_cell for details.
196 194 """
197 195 ipself = self.shell
198 196 raw_cell = cell
199 197 with ipself.builtin_trap:
200 198 cell = ipself.prefilter_manager.prefilter_lines(cell)
201 199
202 200 # Store raw and processed history
203 201 if store_history:
204 202 ipself.history_manager.store_inputs(ipself.execution_count,
205 203 cell, raw_cell)
206 204
207 205 # ipself.logger.log(cell, raw_cell)
208 206
209 207 cell_name = ipself.compile.cache(cell, ipself.execution_count)
210 208
211 209 try:
212 210 code_ast = ast.parse(cell, filename=cell_name)
213 211 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
214 212 # Case 1
215 213 ipself.showsyntaxerror()
216 214 ipself.execution_count += 1
217 215 return None
218 216 except NameError:
219 217 # ignore name errors, because we don't know the remote keys
220 218 pass
221 219
222 220 if store_history:
223 221 # Write output to the database. Does nothing unless
224 222 # history output logging is enabled.
225 223 ipself.history_manager.store_output(ipself.execution_count)
226 224 # Each cell is a *single* input, regardless of how many lines it has
227 225 ipself.execution_count += 1
228 226
229 227 if re.search(r'get_ipython\(\)\.magic\(u?"%?autopx', cell):
230 228 self._disable_autopx()
231 229 return False
232 230 else:
233 231 try:
234 232 result = self.active_view.execute(cell, block=False)
235 233 except:
236 234 ipself.showtraceback()
237 return False
235 return True
238 236 else:
239 return self._maybe_display_output(result)
237 if self.active_view.block:
238 try:
239 result.get()
240 except:
241 self.shell.showtraceback()
242 return True
243 else:
244 self._maybe_display_output(result)
245 return False
240 246
241 247 def pxrun_code(self, code_obj, post_execute=True):
242 248 """drop-in replacement for InteractiveShell.run_code.
243 249
244 250 This executes code remotely, instead of in the local namespace.
245 251
246 252 See InteractiveShell.run_code for details.
247 253 """
248 254 ipself = self.shell
249 255 # check code object for the autopx magic
250 256 if 'get_ipython' in code_obj.co_names and 'magic' in code_obj.co_names and \
251 257 any( [ isinstance(c, basestring) and 'autopx' in c for c in code_obj.co_consts ]):
252 258 self._disable_autopx()
253 259 return False
254 260 else:
255 261 try:
256 262 result = self.active_view.execute(code_obj, block=False)
257 263 except:
258 264 ipself.showtraceback()
259 return False
265 return True
260 266 else:
261 return self._maybe_display_output(result)
267 if self.active_view.block:
268 try:
269 result.get()
270 except:
271 self.shell.showtraceback()
272 return True
273 else:
274 self._maybe_display_output(result)
275 return False
262 276
263 277
264 278
265 279
266 280 _loaded = False
267 281
268 282
269 283 def load_ipython_extension(ip):
270 284 """Load the extension in IPython."""
271 285 global _loaded
272 286 if not _loaded:
273 287 plugin = ParalleMagic(shell=ip, config=ip.config)
274 288 ip.plugin_manager.register_plugin('parallelmagic', plugin)
275 289 _loaded = True
276 290
@@ -1,302 +1,413 b''
1 1 """test View objects"""
2 2 #-------------------------------------------------------------------------------
3 3 # Copyright (C) 2011 The IPython Development Team
4 4 #
5 5 # Distributed under the terms of the BSD License. The full license is in
6 6 # the file COPYING, distributed as part of this software.
7 7 #-------------------------------------------------------------------------------
8 8
9 9 #-------------------------------------------------------------------------------
10 10 # Imports
11 11 #-------------------------------------------------------------------------------
12 12
13 import sys
13 14 import time
14 15 from tempfile import mktemp
16 from StringIO import StringIO
15 17
16 18 import zmq
17 19
18 20 from IPython import parallel as pmod
19 21 from IPython.parallel import error
20 22 from IPython.parallel import AsyncResult, AsyncHubResult, AsyncMapResult
21 23 from IPython.parallel import LoadBalancedView, DirectView
22 24 from IPython.parallel.util import interactive
23 25
24 26 from IPython.parallel.tests import add_engines
25 27
26 28 from .clienttest import ClusterTestCase, segfault, wait, skip_without
27 29
28 30 def setup():
29 31 add_engines(3)
30 32
31 33 class TestView(ClusterTestCase):
32 34
33 35 def test_segfault_task(self):
34 36 """test graceful handling of engine death (balanced)"""
35 37 # self.add_engines(1)
36 38 ar = self.client[-1].apply_async(segfault)
37 39 self.assertRaisesRemote(error.EngineError, ar.get)
38 40 eid = ar.engine_id
39 41 while eid in self.client.ids:
40 42 time.sleep(.01)
41 43 self.client.spin()
42 44
43 45 def test_segfault_mux(self):
44 46 """test graceful handling of engine death (direct)"""
45 47 # self.add_engines(1)
46 48 eid = self.client.ids[-1]
47 49 ar = self.client[eid].apply_async(segfault)
48 50 self.assertRaisesRemote(error.EngineError, ar.get)
49 51 eid = ar.engine_id
50 52 while eid in self.client.ids:
51 53 time.sleep(.01)
52 54 self.client.spin()
53 55
54 56 def test_push_pull(self):
55 57 """test pushing and pulling"""
56 58 data = dict(a=10, b=1.05, c=range(10), d={'e':(1,2),'f':'hi'})
57 59 t = self.client.ids[-1]
58 60 v = self.client[t]
59 61 push = v.push
60 62 pull = v.pull
61 63 v.block=True
62 64 nengines = len(self.client)
63 65 push({'data':data})
64 66 d = pull('data')
65 67 self.assertEquals(d, data)
66 68 self.client[:].push({'data':data})
67 69 d = self.client[:].pull('data', block=True)
68 70 self.assertEquals(d, nengines*[data])
69 71 ar = push({'data':data}, block=False)
70 72 self.assertTrue(isinstance(ar, AsyncResult))
71 73 r = ar.get()
72 74 ar = self.client[:].pull('data', block=False)
73 75 self.assertTrue(isinstance(ar, AsyncResult))
74 76 r = ar.get()
75 77 self.assertEquals(r, nengines*[data])
76 78 self.client[:].push(dict(a=10,b=20))
77 79 r = self.client[:].pull(('a','b'), block=True)
78 80 self.assertEquals(r, nengines*[[10,20]])
79 81
80 82 def test_push_pull_function(self):
81 83 "test pushing and pulling functions"
82 84 def testf(x):
83 85 return 2.0*x
84 86
85 87 t = self.client.ids[-1]
86 88 v = self.client[t]
87 89 v.block=True
88 90 push = v.push
89 91 pull = v.pull
90 92 execute = v.execute
91 93 push({'testf':testf})
92 94 r = pull('testf')
93 95 self.assertEqual(r(1.0), testf(1.0))
94 96 execute('r = testf(10)')
95 97 r = pull('r')
96 98 self.assertEquals(r, testf(10))
97 99 ar = self.client[:].push({'testf':testf}, block=False)
98 100 ar.get()
99 101 ar = self.client[:].pull('testf', block=False)
100 102 rlist = ar.get()
101 103 for r in rlist:
102 104 self.assertEqual(r(1.0), testf(1.0))
103 105 execute("def g(x): return x*x")
104 106 r = pull(('testf','g'))
105 107 self.assertEquals((r[0](10),r[1](10)), (testf(10), 100))
106 108
107 109 def test_push_function_globals(self):
108 110 """test that pushed functions have access to globals"""
109 111 @interactive
110 112 def geta():
111 113 return a
112 114 # self.add_engines(1)
113 115 v = self.client[-1]
114 116 v.block=True
115 117 v['f'] = geta
116 118 self.assertRaisesRemote(NameError, v.execute, 'b=f()')
117 119 v.execute('a=5')
118 120 v.execute('b=f()')
119 121 self.assertEquals(v['b'], 5)
120 122
121 123 def test_push_function_defaults(self):
122 124 """test that pushed functions preserve default args"""
123 125 def echo(a=10):
124 126 return a
125 127 v = self.client[-1]
126 128 v.block=True
127 129 v['f'] = echo
128 130 v.execute('b=f()')
129 131 self.assertEquals(v['b'], 10)
130 132
131 133 def test_get_result(self):
132 134 """test getting results from the Hub."""
133 135 c = pmod.Client(profile='iptest')
134 136 # self.add_engines(1)
135 137 t = c.ids[-1]
136 138 v = c[t]
137 139 v2 = self.client[t]
138 140 ar = v.apply_async(wait, 1)
139 141 # give the monitor time to notice the message
140 142 time.sleep(.25)
141 143 ahr = v2.get_result(ar.msg_ids)
142 144 self.assertTrue(isinstance(ahr, AsyncHubResult))
143 145 self.assertEquals(ahr.get(), ar.get())
144 146 ar2 = v2.get_result(ar.msg_ids)
145 147 self.assertFalse(isinstance(ar2, AsyncHubResult))
146 148 c.spin()
147 149 c.close()
148 150
149 151 def test_run_newline(self):
150 152 """test that run appends newline to files"""
151 153 tmpfile = mktemp()
152 154 with open(tmpfile, 'w') as f:
153 155 f.write("""def g():
154 156 return 5
155 157 """)
156 158 v = self.client[-1]
157 159 v.run(tmpfile, block=True)
158 160 self.assertEquals(v.apply_sync(lambda f: f(), pmod.Reference('g')), 5)
159 161
160 162 def test_apply_tracked(self):
161 163 """test tracking for apply"""
162 164 # self.add_engines(1)
163 165 t = self.client.ids[-1]
164 166 v = self.client[t]
165 167 v.block=False
166 168 def echo(n=1024*1024, **kwargs):
167 169 with v.temp_flags(**kwargs):
168 170 return v.apply(lambda x: x, 'x'*n)
169 171 ar = echo(1, track=False)
170 172 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
171 173 self.assertTrue(ar.sent)
172 174 ar = echo(track=True)
173 175 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
174 176 self.assertEquals(ar.sent, ar._tracker.done)
175 177 ar._tracker.wait()
176 178 self.assertTrue(ar.sent)
177 179
178 180 def test_push_tracked(self):
179 181 t = self.client.ids[-1]
180 182 ns = dict(x='x'*1024*1024)
181 183 v = self.client[t]
182 184 ar = v.push(ns, block=False, track=False)
183 185 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
184 186 self.assertTrue(ar.sent)
185 187
186 188 ar = v.push(ns, block=False, track=True)
187 189 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
188 190 self.assertEquals(ar.sent, ar._tracker.done)
189 191 ar._tracker.wait()
190 192 self.assertTrue(ar.sent)
191 193 ar.get()
192 194
193 195 def test_scatter_tracked(self):
194 196 t = self.client.ids
195 197 x='x'*1024*1024
196 198 ar = self.client[t].scatter('x', x, block=False, track=False)
197 199 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
198 200 self.assertTrue(ar.sent)
199 201
200 202 ar = self.client[t].scatter('x', x, block=False, track=True)
201 203 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
202 204 self.assertEquals(ar.sent, ar._tracker.done)
203 205 ar._tracker.wait()
204 206 self.assertTrue(ar.sent)
205 207 ar.get()
206 208
207 209 def test_remote_reference(self):
208 210 v = self.client[-1]
209 211 v['a'] = 123
210 212 ra = pmod.Reference('a')
211 213 b = v.apply_sync(lambda x: x, ra)
212 214 self.assertEquals(b, 123)
213 215
214 216
215 217 def test_scatter_gather(self):
216 218 view = self.client[:]
217 219 seq1 = range(16)
218 220 view.scatter('a', seq1)
219 221 seq2 = view.gather('a', block=True)
220 222 self.assertEquals(seq2, seq1)
221 223 self.assertRaisesRemote(NameError, view.gather, 'asdf', block=True)
222 224
223 225 @skip_without('numpy')
224 226 def test_scatter_gather_numpy(self):
225 227 import numpy
226 228 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
227 229 view = self.client[:]
228 230 a = numpy.arange(64)
229 231 view.scatter('a', a)
230 232 b = view.gather('a', block=True)
231 233 assert_array_equal(b, a)
232 234
233 235 def test_map(self):
234 236 view = self.client[:]
235 237 def f(x):
236 238 return x**2
237 239 data = range(16)
238 240 r = view.map_sync(f, data)
239 241 self.assertEquals(r, map(f, data))
240 242
241 243 def test_scatterGatherNonblocking(self):
242 244 data = range(16)
243 245 view = self.client[:]
244 246 view.scatter('a', data, block=False)
245 247 ar = view.gather('a', block=False)
246 248 self.assertEquals(ar.get(), data)
247 249
248 250 @skip_without('numpy')
249 251 def test_scatter_gather_numpy_nonblocking(self):
250 252 import numpy
251 253 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
252 254 a = numpy.arange(64)
253 255 view = self.client[:]
254 256 ar = view.scatter('a', a, block=False)
255 257 self.assertTrue(isinstance(ar, AsyncResult))
256 258 amr = view.gather('a', block=False)
257 259 self.assertTrue(isinstance(amr, AsyncMapResult))
258 260 assert_array_equal(amr.get(), a)
259 261
260 262 def test_execute(self):
261 263 view = self.client[:]
262 264 # self.client.debug=True
263 265 execute = view.execute
264 266 ar = execute('c=30', block=False)
265 267 self.assertTrue(isinstance(ar, AsyncResult))
266 268 ar = execute('d=[0,1,2]', block=False)
267 269 self.client.wait(ar, 1)
268 270 self.assertEquals(len(ar.get()), len(self.client))
269 271 for c in view['c']:
270 272 self.assertEquals(c, 30)
271 273
272 274 def test_abort(self):
273 275 view = self.client[-1]
274 276 ar = view.execute('import time; time.sleep(0.25)', block=False)
275 277 ar2 = view.apply_async(lambda : 2)
276 278 ar3 = view.apply_async(lambda : 3)
277 279 view.abort(ar2)
278 280 view.abort(ar3.msg_ids)
279 281 self.assertRaises(error.TaskAborted, ar2.get)
280 282 self.assertRaises(error.TaskAborted, ar3.get)
281 283
282 284 def test_temp_flags(self):
283 285 view = self.client[-1]
284 286 view.block=True
285 287 with view.temp_flags(block=False):
286 288 self.assertFalse(view.block)
287 289 self.assertTrue(view.block)
288 290
289 291 def test_importer(self):
290 292 view = self.client[-1]
291 293 view.clear(block=True)
292 294 with view.importer:
293 295 import re
294 296
295 297 @interactive
296 298 def findall(pat, s):
297 299 # this globals() step isn't necessary in real code
298 300 # only to prevent a closure in the test
299 301 return globals()['re'].findall(pat, s)
300 302
301 303 self.assertEquals(view.apply_sync(findall, '\w+', 'hello world'), 'hello world'.split())
302 304
305 # parallel magic tests
306
307 def test_magic_px_blocking(self):
308 ip = get_ipython()
309 v = self.client[-1]
310 v.activate()
311 v.block=True
312
313 ip.magic_px('a=5')
314 self.assertEquals(v['a'], 5)
315 ip.magic_px('a=10')
316 self.assertEquals(v['a'], 10)
317 sio = StringIO()
318 savestdout = sys.stdout
319 sys.stdout = sio
320 ip.magic_px('print a')
321 sys.stdout = savestdout
322 sio.read()
323 self.assertTrue('[stdout:%i]'%v.targets in sio.buf)
324 self.assertRaisesRemote(ZeroDivisionError, ip.magic_px, '1/0')
325
326 def test_magic_px_nonblocking(self):
327 ip = get_ipython()
328 v = self.client[-1]
329 v.activate()
330 v.block=False
331
332 ip.magic_px('a=5')
333 self.assertEquals(v['a'], 5)
334 ip.magic_px('a=10')
335 self.assertEquals(v['a'], 10)
336 sio = StringIO()
337 savestdout = sys.stdout
338 sys.stdout = sio
339 ip.magic_px('print a')
340 sys.stdout = savestdout
341 sio.read()
342 self.assertFalse('[stdout:%i]'%v.targets in sio.buf)
343 ip.magic_px('1/0')
344 ar = v.get_result(-1)
345 self.assertRaisesRemote(ZeroDivisionError, ar.get)
346
347 def test_magic_autopx_blocking(self):
348 ip = get_ipython()
349 v = self.client[-1]
350 v.activate()
351 v.block=True
352
353 sio = StringIO()
354 savestdout = sys.stdout
355 sys.stdout = sio
356 ip.magic_autopx()
357 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
358 ip.run_cell('print b')
359 ip.run_cell("b/c")
360 ip.run_code(compile('b*=2', '', 'single'))
361 ip.magic_autopx()
362 sys.stdout = savestdout
363 sio.read()
364 output = sio.buf.strip()
365 self.assertTrue(output.startswith('%autopx enabled'))
366 self.assertTrue(output.endswith('%autopx disabled'))
367 self.assertTrue('RemoteError: ZeroDivisionError' in output)
368 ar = v.get_result(-2)
369 self.assertEquals(v['a'], 5)
370 self.assertEquals(v['b'], 20)
371 self.assertRaisesRemote(ZeroDivisionError, ar.get)
372
373 def test_magic_autopx_nonblocking(self):
374 ip = get_ipython()
375 v = self.client[-1]
376 v.activate()
377 v.block=False
378
379 sio = StringIO()
380 savestdout = sys.stdout
381 sys.stdout = sio
382 ip.magic_autopx()
383 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
384 ip.run_cell('print b')
385 ip.run_cell("b/c")
386 ip.run_code(compile('b*=2', '', 'single'))
387 ip.magic_autopx()
388 sys.stdout = savestdout
389 sio.read()
390 output = sio.buf.strip()
391 self.assertTrue(output.startswith('%autopx enabled'))
392 self.assertTrue(output.endswith('%autopx disabled'))
393 self.assertFalse('ZeroDivisionError' in output)
394 ar = v.get_result(-2)
395 self.assertEquals(v['a'], 5)
396 self.assertEquals(v['b'], 20)
397 self.assertRaisesRemote(ZeroDivisionError, ar.get)
398
399 def test_magic_result(self):
400 ip = get_ipython()
401 v = self.client[-1]
402 v.activate()
403 v['a'] = 111
404 ra = v['a']
405
406 ar = ip.magic_result()
407 self.assertEquals(ar.msg_ids, [v.history[-1]])
408 self.assertEquals(ar.get(), 111)
409 ar = ip.magic_result('-2')
410 self.assertEquals(ar.msg_ids, [v.history[-2]])
411
412
413
General Comments 0
You need to be logged in to leave comments. Login now