##// END OF EJS Templates
use eval to uncan References...
MinRK -
Show More
@@ -1,493 +1,507 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """test View objects
2 """test View objects
3
3
4 Authors:
4 Authors:
5
5
6 * Min RK
6 * Min RK
7 """
7 """
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
9 # Copyright (C) 2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18
18
19 import sys
19 import sys
20 import time
20 import time
21 from tempfile import mktemp
21 from tempfile import mktemp
22 from StringIO import StringIO
22 from StringIO import StringIO
23
23
24 import zmq
24 import zmq
25 from nose import SkipTest
25 from nose import SkipTest
26
26
27 from IPython.testing import decorators as dec
27 from IPython.testing import decorators as dec
28
28
29 from IPython import parallel as pmod
29 from IPython import parallel as pmod
30 from IPython.parallel import error
30 from IPython.parallel import error
31 from IPython.parallel import AsyncResult, AsyncHubResult, AsyncMapResult
31 from IPython.parallel import AsyncResult, AsyncHubResult, AsyncMapResult
32 from IPython.parallel import DirectView
32 from IPython.parallel import DirectView
33 from IPython.parallel.util import interactive
33 from IPython.parallel.util import interactive
34
34
35 from IPython.parallel.tests import add_engines
35 from IPython.parallel.tests import add_engines
36
36
37 from .clienttest import ClusterTestCase, crash, wait, skip_without
37 from .clienttest import ClusterTestCase, crash, wait, skip_without
38
38
39 def setup():
39 def setup():
40 add_engines(3)
40 add_engines(3)
41
41
42 class TestView(ClusterTestCase):
42 class TestView(ClusterTestCase):
43
43
44 def test_z_crash_mux(self):
44 def test_z_crash_mux(self):
45 """test graceful handling of engine death (direct)"""
45 """test graceful handling of engine death (direct)"""
46 raise SkipTest("crash tests disabled, due to undesirable crash reports")
46 raise SkipTest("crash tests disabled, due to undesirable crash reports")
47 # self.add_engines(1)
47 # self.add_engines(1)
48 eid = self.client.ids[-1]
48 eid = self.client.ids[-1]
49 ar = self.client[eid].apply_async(crash)
49 ar = self.client[eid].apply_async(crash)
50 self.assertRaisesRemote(error.EngineError, ar.get, 10)
50 self.assertRaisesRemote(error.EngineError, ar.get, 10)
51 eid = ar.engine_id
51 eid = ar.engine_id
52 tic = time.time()
52 tic = time.time()
53 while eid in self.client.ids and time.time()-tic < 5:
53 while eid in self.client.ids and time.time()-tic < 5:
54 time.sleep(.01)
54 time.sleep(.01)
55 self.client.spin()
55 self.client.spin()
56 self.assertFalse(eid in self.client.ids, "Engine should have died")
56 self.assertFalse(eid in self.client.ids, "Engine should have died")
57
57
58 def test_push_pull(self):
58 def test_push_pull(self):
59 """test pushing and pulling"""
59 """test pushing and pulling"""
60 data = dict(a=10, b=1.05, c=range(10), d={'e':(1,2),'f':'hi'})
60 data = dict(a=10, b=1.05, c=range(10), d={'e':(1,2),'f':'hi'})
61 t = self.client.ids[-1]
61 t = self.client.ids[-1]
62 v = self.client[t]
62 v = self.client[t]
63 push = v.push
63 push = v.push
64 pull = v.pull
64 pull = v.pull
65 v.block=True
65 v.block=True
66 nengines = len(self.client)
66 nengines = len(self.client)
67 push({'data':data})
67 push({'data':data})
68 d = pull('data')
68 d = pull('data')
69 self.assertEquals(d, data)
69 self.assertEquals(d, data)
70 self.client[:].push({'data':data})
70 self.client[:].push({'data':data})
71 d = self.client[:].pull('data', block=True)
71 d = self.client[:].pull('data', block=True)
72 self.assertEquals(d, nengines*[data])
72 self.assertEquals(d, nengines*[data])
73 ar = push({'data':data}, block=False)
73 ar = push({'data':data}, block=False)
74 self.assertTrue(isinstance(ar, AsyncResult))
74 self.assertTrue(isinstance(ar, AsyncResult))
75 r = ar.get()
75 r = ar.get()
76 ar = self.client[:].pull('data', block=False)
76 ar = self.client[:].pull('data', block=False)
77 self.assertTrue(isinstance(ar, AsyncResult))
77 self.assertTrue(isinstance(ar, AsyncResult))
78 r = ar.get()
78 r = ar.get()
79 self.assertEquals(r, nengines*[data])
79 self.assertEquals(r, nengines*[data])
80 self.client[:].push(dict(a=10,b=20))
80 self.client[:].push(dict(a=10,b=20))
81 r = self.client[:].pull(('a','b'), block=True)
81 r = self.client[:].pull(('a','b'), block=True)
82 self.assertEquals(r, nengines*[[10,20]])
82 self.assertEquals(r, nengines*[[10,20]])
83
83
84 def test_push_pull_function(self):
84 def test_push_pull_function(self):
85 "test pushing and pulling functions"
85 "test pushing and pulling functions"
86 def testf(x):
86 def testf(x):
87 return 2.0*x
87 return 2.0*x
88
88
89 t = self.client.ids[-1]
89 t = self.client.ids[-1]
90 v = self.client[t]
90 v = self.client[t]
91 v.block=True
91 v.block=True
92 push = v.push
92 push = v.push
93 pull = v.pull
93 pull = v.pull
94 execute = v.execute
94 execute = v.execute
95 push({'testf':testf})
95 push({'testf':testf})
96 r = pull('testf')
96 r = pull('testf')
97 self.assertEqual(r(1.0), testf(1.0))
97 self.assertEqual(r(1.0), testf(1.0))
98 execute('r = testf(10)')
98 execute('r = testf(10)')
99 r = pull('r')
99 r = pull('r')
100 self.assertEquals(r, testf(10))
100 self.assertEquals(r, testf(10))
101 ar = self.client[:].push({'testf':testf}, block=False)
101 ar = self.client[:].push({'testf':testf}, block=False)
102 ar.get()
102 ar.get()
103 ar = self.client[:].pull('testf', block=False)
103 ar = self.client[:].pull('testf', block=False)
104 rlist = ar.get()
104 rlist = ar.get()
105 for r in rlist:
105 for r in rlist:
106 self.assertEqual(r(1.0), testf(1.0))
106 self.assertEqual(r(1.0), testf(1.0))
107 execute("def g(x): return x*x")
107 execute("def g(x): return x*x")
108 r = pull(('testf','g'))
108 r = pull(('testf','g'))
109 self.assertEquals((r[0](10),r[1](10)), (testf(10), 100))
109 self.assertEquals((r[0](10),r[1](10)), (testf(10), 100))
110
110
111 def test_push_function_globals(self):
111 def test_push_function_globals(self):
112 """test that pushed functions have access to globals"""
112 """test that pushed functions have access to globals"""
113 @interactive
113 @interactive
114 def geta():
114 def geta():
115 return a
115 return a
116 # self.add_engines(1)
116 # self.add_engines(1)
117 v = self.client[-1]
117 v = self.client[-1]
118 v.block=True
118 v.block=True
119 v['f'] = geta
119 v['f'] = geta
120 self.assertRaisesRemote(NameError, v.execute, 'b=f()')
120 self.assertRaisesRemote(NameError, v.execute, 'b=f()')
121 v.execute('a=5')
121 v.execute('a=5')
122 v.execute('b=f()')
122 v.execute('b=f()')
123 self.assertEquals(v['b'], 5)
123 self.assertEquals(v['b'], 5)
124
124
125 def test_push_function_defaults(self):
125 def test_push_function_defaults(self):
126 """test that pushed functions preserve default args"""
126 """test that pushed functions preserve default args"""
127 def echo(a=10):
127 def echo(a=10):
128 return a
128 return a
129 v = self.client[-1]
129 v = self.client[-1]
130 v.block=True
130 v.block=True
131 v['f'] = echo
131 v['f'] = echo
132 v.execute('b=f()')
132 v.execute('b=f()')
133 self.assertEquals(v['b'], 10)
133 self.assertEquals(v['b'], 10)
134
134
135 def test_get_result(self):
135 def test_get_result(self):
136 """test getting results from the Hub."""
136 """test getting results from the Hub."""
137 c = pmod.Client(profile='iptest')
137 c = pmod.Client(profile='iptest')
138 # self.add_engines(1)
138 # self.add_engines(1)
139 t = c.ids[-1]
139 t = c.ids[-1]
140 v = c[t]
140 v = c[t]
141 v2 = self.client[t]
141 v2 = self.client[t]
142 ar = v.apply_async(wait, 1)
142 ar = v.apply_async(wait, 1)
143 # give the monitor time to notice the message
143 # give the monitor time to notice the message
144 time.sleep(.25)
144 time.sleep(.25)
145 ahr = v2.get_result(ar.msg_ids)
145 ahr = v2.get_result(ar.msg_ids)
146 self.assertTrue(isinstance(ahr, AsyncHubResult))
146 self.assertTrue(isinstance(ahr, AsyncHubResult))
147 self.assertEquals(ahr.get(), ar.get())
147 self.assertEquals(ahr.get(), ar.get())
148 ar2 = v2.get_result(ar.msg_ids)
148 ar2 = v2.get_result(ar.msg_ids)
149 self.assertFalse(isinstance(ar2, AsyncHubResult))
149 self.assertFalse(isinstance(ar2, AsyncHubResult))
150 c.spin()
150 c.spin()
151 c.close()
151 c.close()
152
152
153 def test_run_newline(self):
153 def test_run_newline(self):
154 """test that run appends newline to files"""
154 """test that run appends newline to files"""
155 tmpfile = mktemp()
155 tmpfile = mktemp()
156 with open(tmpfile, 'w') as f:
156 with open(tmpfile, 'w') as f:
157 f.write("""def g():
157 f.write("""def g():
158 return 5
158 return 5
159 """)
159 """)
160 v = self.client[-1]
160 v = self.client[-1]
161 v.run(tmpfile, block=True)
161 v.run(tmpfile, block=True)
162 self.assertEquals(v.apply_sync(lambda f: f(), pmod.Reference('g')), 5)
162 self.assertEquals(v.apply_sync(lambda f: f(), pmod.Reference('g')), 5)
163
163
164 def test_apply_tracked(self):
164 def test_apply_tracked(self):
165 """test tracking for apply"""
165 """test tracking for apply"""
166 # self.add_engines(1)
166 # self.add_engines(1)
167 t = self.client.ids[-1]
167 t = self.client.ids[-1]
168 v = self.client[t]
168 v = self.client[t]
169 v.block=False
169 v.block=False
170 def echo(n=1024*1024, **kwargs):
170 def echo(n=1024*1024, **kwargs):
171 with v.temp_flags(**kwargs):
171 with v.temp_flags(**kwargs):
172 return v.apply(lambda x: x, 'x'*n)
172 return v.apply(lambda x: x, 'x'*n)
173 ar = echo(1, track=False)
173 ar = echo(1, track=False)
174 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
174 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
175 self.assertTrue(ar.sent)
175 self.assertTrue(ar.sent)
176 ar = echo(track=True)
176 ar = echo(track=True)
177 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
177 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
178 self.assertEquals(ar.sent, ar._tracker.done)
178 self.assertEquals(ar.sent, ar._tracker.done)
179 ar._tracker.wait()
179 ar._tracker.wait()
180 self.assertTrue(ar.sent)
180 self.assertTrue(ar.sent)
181
181
182 def test_push_tracked(self):
182 def test_push_tracked(self):
183 t = self.client.ids[-1]
183 t = self.client.ids[-1]
184 ns = dict(x='x'*1024*1024)
184 ns = dict(x='x'*1024*1024)
185 v = self.client[t]
185 v = self.client[t]
186 ar = v.push(ns, block=False, track=False)
186 ar = v.push(ns, block=False, track=False)
187 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
187 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
188 self.assertTrue(ar.sent)
188 self.assertTrue(ar.sent)
189
189
190 ar = v.push(ns, block=False, track=True)
190 ar = v.push(ns, block=False, track=True)
191 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
191 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
192 ar._tracker.wait()
192 ar._tracker.wait()
193 self.assertEquals(ar.sent, ar._tracker.done)
193 self.assertEquals(ar.sent, ar._tracker.done)
194 self.assertTrue(ar.sent)
194 self.assertTrue(ar.sent)
195 ar.get()
195 ar.get()
196
196
197 def test_scatter_tracked(self):
197 def test_scatter_tracked(self):
198 t = self.client.ids
198 t = self.client.ids
199 x='x'*1024*1024
199 x='x'*1024*1024
200 ar = self.client[t].scatter('x', x, block=False, track=False)
200 ar = self.client[t].scatter('x', x, block=False, track=False)
201 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
201 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
202 self.assertTrue(ar.sent)
202 self.assertTrue(ar.sent)
203
203
204 ar = self.client[t].scatter('x', x, block=False, track=True)
204 ar = self.client[t].scatter('x', x, block=False, track=True)
205 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
205 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
206 self.assertEquals(ar.sent, ar._tracker.done)
206 self.assertEquals(ar.sent, ar._tracker.done)
207 ar._tracker.wait()
207 ar._tracker.wait()
208 self.assertTrue(ar.sent)
208 self.assertTrue(ar.sent)
209 ar.get()
209 ar.get()
210
210
211 def test_remote_reference(self):
211 def test_remote_reference(self):
212 v = self.client[-1]
212 v = self.client[-1]
213 v['a'] = 123
213 v['a'] = 123
214 ra = pmod.Reference('a')
214 ra = pmod.Reference('a')
215 b = v.apply_sync(lambda x: x, ra)
215 b = v.apply_sync(lambda x: x, ra)
216 self.assertEquals(b, 123)
216 self.assertEquals(b, 123)
217
217
218
218
219 def test_scatter_gather(self):
219 def test_scatter_gather(self):
220 view = self.client[:]
220 view = self.client[:]
221 seq1 = range(16)
221 seq1 = range(16)
222 view.scatter('a', seq1)
222 view.scatter('a', seq1)
223 seq2 = view.gather('a', block=True)
223 seq2 = view.gather('a', block=True)
224 self.assertEquals(seq2, seq1)
224 self.assertEquals(seq2, seq1)
225 self.assertRaisesRemote(NameError, view.gather, 'asdf', block=True)
225 self.assertRaisesRemote(NameError, view.gather, 'asdf', block=True)
226
226
227 @skip_without('numpy')
227 @skip_without('numpy')
228 def test_scatter_gather_numpy(self):
228 def test_scatter_gather_numpy(self):
229 import numpy
229 import numpy
230 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
230 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
231 view = self.client[:]
231 view = self.client[:]
232 a = numpy.arange(64)
232 a = numpy.arange(64)
233 view.scatter('a', a)
233 view.scatter('a', a)
234 b = view.gather('a', block=True)
234 b = view.gather('a', block=True)
235 assert_array_equal(b, a)
235 assert_array_equal(b, a)
236
236
237 def test_map(self):
237 def test_map(self):
238 view = self.client[:]
238 view = self.client[:]
239 def f(x):
239 def f(x):
240 return x**2
240 return x**2
241 data = range(16)
241 data = range(16)
242 r = view.map_sync(f, data)
242 r = view.map_sync(f, data)
243 self.assertEquals(r, map(f, data))
243 self.assertEquals(r, map(f, data))
244
244
245 def test_map_iterable(self):
245 def test_map_iterable(self):
246 """test map on iterables (direct)"""
246 """test map on iterables (direct)"""
247 view = self.client[:]
247 view = self.client[:]
248 # 101 is prime, so it won't be evenly distributed
248 # 101 is prime, so it won't be evenly distributed
249 arr = range(101)
249 arr = range(101)
250 # ensure it will be an iterator, even in Python 3
250 # ensure it will be an iterator, even in Python 3
251 it = iter(arr)
251 it = iter(arr)
252 r = view.map_sync(lambda x:x, arr)
252 r = view.map_sync(lambda x:x, arr)
253 self.assertEquals(r, list(arr))
253 self.assertEquals(r, list(arr))
254
254
255 def test_scatterGatherNonblocking(self):
255 def test_scatterGatherNonblocking(self):
256 data = range(16)
256 data = range(16)
257 view = self.client[:]
257 view = self.client[:]
258 view.scatter('a', data, block=False)
258 view.scatter('a', data, block=False)
259 ar = view.gather('a', block=False)
259 ar = view.gather('a', block=False)
260 self.assertEquals(ar.get(), data)
260 self.assertEquals(ar.get(), data)
261
261
262 @skip_without('numpy')
262 @skip_without('numpy')
263 def test_scatter_gather_numpy_nonblocking(self):
263 def test_scatter_gather_numpy_nonblocking(self):
264 import numpy
264 import numpy
265 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
265 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
266 a = numpy.arange(64)
266 a = numpy.arange(64)
267 view = self.client[:]
267 view = self.client[:]
268 ar = view.scatter('a', a, block=False)
268 ar = view.scatter('a', a, block=False)
269 self.assertTrue(isinstance(ar, AsyncResult))
269 self.assertTrue(isinstance(ar, AsyncResult))
270 amr = view.gather('a', block=False)
270 amr = view.gather('a', block=False)
271 self.assertTrue(isinstance(amr, AsyncMapResult))
271 self.assertTrue(isinstance(amr, AsyncMapResult))
272 assert_array_equal(amr.get(), a)
272 assert_array_equal(amr.get(), a)
273
273
274 def test_execute(self):
274 def test_execute(self):
275 view = self.client[:]
275 view = self.client[:]
276 # self.client.debug=True
276 # self.client.debug=True
277 execute = view.execute
277 execute = view.execute
278 ar = execute('c=30', block=False)
278 ar = execute('c=30', block=False)
279 self.assertTrue(isinstance(ar, AsyncResult))
279 self.assertTrue(isinstance(ar, AsyncResult))
280 ar = execute('d=[0,1,2]', block=False)
280 ar = execute('d=[0,1,2]', block=False)
281 self.client.wait(ar, 1)
281 self.client.wait(ar, 1)
282 self.assertEquals(len(ar.get()), len(self.client))
282 self.assertEquals(len(ar.get()), len(self.client))
283 for c in view['c']:
283 for c in view['c']:
284 self.assertEquals(c, 30)
284 self.assertEquals(c, 30)
285
285
286 def test_abort(self):
286 def test_abort(self):
287 view = self.client[-1]
287 view = self.client[-1]
288 ar = view.execute('import time; time.sleep(1)', block=False)
288 ar = view.execute('import time; time.sleep(1)', block=False)
289 ar2 = view.apply_async(lambda : 2)
289 ar2 = view.apply_async(lambda : 2)
290 ar3 = view.apply_async(lambda : 3)
290 ar3 = view.apply_async(lambda : 3)
291 view.abort(ar2)
291 view.abort(ar2)
292 view.abort(ar3.msg_ids)
292 view.abort(ar3.msg_ids)
293 self.assertRaises(error.TaskAborted, ar2.get)
293 self.assertRaises(error.TaskAborted, ar2.get)
294 self.assertRaises(error.TaskAborted, ar3.get)
294 self.assertRaises(error.TaskAborted, ar3.get)
295
295
296 def test_abort_all(self):
296 def test_abort_all(self):
297 """view.abort() aborts all outstanding tasks"""
297 """view.abort() aborts all outstanding tasks"""
298 view = self.client[-1]
298 view = self.client[-1]
299 ars = [ view.apply_async(time.sleep, 1) for i in range(10) ]
299 ars = [ view.apply_async(time.sleep, 1) for i in range(10) ]
300 view.abort()
300 view.abort()
301 view.wait(timeout=5)
301 view.wait(timeout=5)
302 for ar in ars[5:]:
302 for ar in ars[5:]:
303 self.assertRaises(error.TaskAborted, ar.get)
303 self.assertRaises(error.TaskAborted, ar.get)
304
304
305 def test_temp_flags(self):
305 def test_temp_flags(self):
306 view = self.client[-1]
306 view = self.client[-1]
307 view.block=True
307 view.block=True
308 with view.temp_flags(block=False):
308 with view.temp_flags(block=False):
309 self.assertFalse(view.block)
309 self.assertFalse(view.block)
310 self.assertTrue(view.block)
310 self.assertTrue(view.block)
311
311
312 @dec.known_failure_py3
312 @dec.known_failure_py3
313 def test_importer(self):
313 def test_importer(self):
314 view = self.client[-1]
314 view = self.client[-1]
315 view.clear(block=True)
315 view.clear(block=True)
316 with view.importer:
316 with view.importer:
317 import re
317 import re
318
318
319 @interactive
319 @interactive
320 def findall(pat, s):
320 def findall(pat, s):
321 # this globals() step isn't necessary in real code
321 # this globals() step isn't necessary in real code
322 # only to prevent a closure in the test
322 # only to prevent a closure in the test
323 re = globals()['re']
323 re = globals()['re']
324 return re.findall(pat, s)
324 return re.findall(pat, s)
325
325
326 self.assertEquals(view.apply_sync(findall, '\w+', 'hello world'), 'hello world'.split())
326 self.assertEquals(view.apply_sync(findall, '\w+', 'hello world'), 'hello world'.split())
327
327
328 # parallel magic tests
328 # parallel magic tests
329
329
330 def test_magic_px_blocking(self):
330 def test_magic_px_blocking(self):
331 ip = get_ipython()
331 ip = get_ipython()
332 v = self.client[-1]
332 v = self.client[-1]
333 v.activate()
333 v.activate()
334 v.block=True
334 v.block=True
335
335
336 ip.magic_px('a=5')
336 ip.magic_px('a=5')
337 self.assertEquals(v['a'], 5)
337 self.assertEquals(v['a'], 5)
338 ip.magic_px('a=10')
338 ip.magic_px('a=10')
339 self.assertEquals(v['a'], 10)
339 self.assertEquals(v['a'], 10)
340 sio = StringIO()
340 sio = StringIO()
341 savestdout = sys.stdout
341 savestdout = sys.stdout
342 sys.stdout = sio
342 sys.stdout = sio
343 # just 'print a' worst ~99% of the time, but this ensures that
343 # just 'print a' worst ~99% of the time, but this ensures that
344 # the stdout message has arrived when the result is finished:
344 # the stdout message has arrived when the result is finished:
345 ip.magic_px('import sys,time;print (a); sys.stdout.flush();time.sleep(0.2)')
345 ip.magic_px('import sys,time;print (a); sys.stdout.flush();time.sleep(0.2)')
346 sys.stdout = savestdout
346 sys.stdout = savestdout
347 buf = sio.getvalue()
347 buf = sio.getvalue()
348 self.assertTrue('[stdout:' in buf, buf)
348 self.assertTrue('[stdout:' in buf, buf)
349 self.assertTrue(buf.rstrip().endswith('10'))
349 self.assertTrue(buf.rstrip().endswith('10'))
350 self.assertRaisesRemote(ZeroDivisionError, ip.magic_px, '1/0')
350 self.assertRaisesRemote(ZeroDivisionError, ip.magic_px, '1/0')
351
351
352 def test_magic_px_nonblocking(self):
352 def test_magic_px_nonblocking(self):
353 ip = get_ipython()
353 ip = get_ipython()
354 v = self.client[-1]
354 v = self.client[-1]
355 v.activate()
355 v.activate()
356 v.block=False
356 v.block=False
357
357
358 ip.magic_px('a=5')
358 ip.magic_px('a=5')
359 self.assertEquals(v['a'], 5)
359 self.assertEquals(v['a'], 5)
360 ip.magic_px('a=10')
360 ip.magic_px('a=10')
361 self.assertEquals(v['a'], 10)
361 self.assertEquals(v['a'], 10)
362 sio = StringIO()
362 sio = StringIO()
363 savestdout = sys.stdout
363 savestdout = sys.stdout
364 sys.stdout = sio
364 sys.stdout = sio
365 ip.magic_px('print a')
365 ip.magic_px('print a')
366 sys.stdout = savestdout
366 sys.stdout = savestdout
367 buf = sio.getvalue()
367 buf = sio.getvalue()
368 self.assertFalse('[stdout:%i]'%v.targets in buf)
368 self.assertFalse('[stdout:%i]'%v.targets in buf)
369 ip.magic_px('1/0')
369 ip.magic_px('1/0')
370 ar = v.get_result(-1)
370 ar = v.get_result(-1)
371 self.assertRaisesRemote(ZeroDivisionError, ar.get)
371 self.assertRaisesRemote(ZeroDivisionError, ar.get)
372
372
373 def test_magic_autopx_blocking(self):
373 def test_magic_autopx_blocking(self):
374 ip = get_ipython()
374 ip = get_ipython()
375 v = self.client[-1]
375 v = self.client[-1]
376 v.activate()
376 v.activate()
377 v.block=True
377 v.block=True
378
378
379 sio = StringIO()
379 sio = StringIO()
380 savestdout = sys.stdout
380 savestdout = sys.stdout
381 sys.stdout = sio
381 sys.stdout = sio
382 ip.magic_autopx()
382 ip.magic_autopx()
383 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
383 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
384 ip.run_cell('print b')
384 ip.run_cell('print b')
385 ip.run_cell("b/c")
385 ip.run_cell("b/c")
386 ip.run_code(compile('b*=2', '', 'single'))
386 ip.run_code(compile('b*=2', '', 'single'))
387 ip.magic_autopx()
387 ip.magic_autopx()
388 sys.stdout = savestdout
388 sys.stdout = savestdout
389 output = sio.getvalue().strip()
389 output = sio.getvalue().strip()
390 self.assertTrue(output.startswith('%autopx enabled'))
390 self.assertTrue(output.startswith('%autopx enabled'))
391 self.assertTrue(output.endswith('%autopx disabled'))
391 self.assertTrue(output.endswith('%autopx disabled'))
392 self.assertTrue('RemoteError: ZeroDivisionError' in output)
392 self.assertTrue('RemoteError: ZeroDivisionError' in output)
393 ar = v.get_result(-2)
393 ar = v.get_result(-2)
394 self.assertEquals(v['a'], 5)
394 self.assertEquals(v['a'], 5)
395 self.assertEquals(v['b'], 20)
395 self.assertEquals(v['b'], 20)
396 self.assertRaisesRemote(ZeroDivisionError, ar.get)
396 self.assertRaisesRemote(ZeroDivisionError, ar.get)
397
397
398 def test_magic_autopx_nonblocking(self):
398 def test_magic_autopx_nonblocking(self):
399 ip = get_ipython()
399 ip = get_ipython()
400 v = self.client[-1]
400 v = self.client[-1]
401 v.activate()
401 v.activate()
402 v.block=False
402 v.block=False
403
403
404 sio = StringIO()
404 sio = StringIO()
405 savestdout = sys.stdout
405 savestdout = sys.stdout
406 sys.stdout = sio
406 sys.stdout = sio
407 ip.magic_autopx()
407 ip.magic_autopx()
408 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
408 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
409 ip.run_cell('print b')
409 ip.run_cell('print b')
410 ip.run_cell("b/c")
410 ip.run_cell("b/c")
411 ip.run_code(compile('b*=2', '', 'single'))
411 ip.run_code(compile('b*=2', '', 'single'))
412 ip.magic_autopx()
412 ip.magic_autopx()
413 sys.stdout = savestdout
413 sys.stdout = savestdout
414 output = sio.getvalue().strip()
414 output = sio.getvalue().strip()
415 self.assertTrue(output.startswith('%autopx enabled'))
415 self.assertTrue(output.startswith('%autopx enabled'))
416 self.assertTrue(output.endswith('%autopx disabled'))
416 self.assertTrue(output.endswith('%autopx disabled'))
417 self.assertFalse('ZeroDivisionError' in output)
417 self.assertFalse('ZeroDivisionError' in output)
418 ar = v.get_result(-2)
418 ar = v.get_result(-2)
419 self.assertEquals(v['a'], 5)
419 self.assertEquals(v['a'], 5)
420 self.assertEquals(v['b'], 20)
420 self.assertEquals(v['b'], 20)
421 self.assertRaisesRemote(ZeroDivisionError, ar.get)
421 self.assertRaisesRemote(ZeroDivisionError, ar.get)
422
422
423 def test_magic_result(self):
423 def test_magic_result(self):
424 ip = get_ipython()
424 ip = get_ipython()
425 v = self.client[-1]
425 v = self.client[-1]
426 v.activate()
426 v.activate()
427 v['a'] = 111
427 v['a'] = 111
428 ra = v['a']
428 ra = v['a']
429
429
430 ar = ip.magic_result()
430 ar = ip.magic_result()
431 self.assertEquals(ar.msg_ids, [v.history[-1]])
431 self.assertEquals(ar.msg_ids, [v.history[-1]])
432 self.assertEquals(ar.get(), 111)
432 self.assertEquals(ar.get(), 111)
433 ar = ip.magic_result('-2')
433 ar = ip.magic_result('-2')
434 self.assertEquals(ar.msg_ids, [v.history[-2]])
434 self.assertEquals(ar.msg_ids, [v.history[-2]])
435
435
436 def test_unicode_execute(self):
436 def test_unicode_execute(self):
437 """test executing unicode strings"""
437 """test executing unicode strings"""
438 v = self.client[-1]
438 v = self.client[-1]
439 v.block=True
439 v.block=True
440 if sys.version_info[0] >= 3:
440 if sys.version_info[0] >= 3:
441 code="a='é'"
441 code="a='é'"
442 else:
442 else:
443 code=u"a=u'é'"
443 code=u"a=u'é'"
444 v.execute(code)
444 v.execute(code)
445 self.assertEquals(v['a'], u'é')
445 self.assertEquals(v['a'], u'é')
446
446
447 def test_unicode_apply_result(self):
447 def test_unicode_apply_result(self):
448 """test unicode apply results"""
448 """test unicode apply results"""
449 v = self.client[-1]
449 v = self.client[-1]
450 r = v.apply_sync(lambda : u'é')
450 r = v.apply_sync(lambda : u'é')
451 self.assertEquals(r, u'é')
451 self.assertEquals(r, u'é')
452
452
453 def test_unicode_apply_arg(self):
453 def test_unicode_apply_arg(self):
454 """test passing unicode arguments to apply"""
454 """test passing unicode arguments to apply"""
455 v = self.client[-1]
455 v = self.client[-1]
456
456
457 @interactive
457 @interactive
458 def check_unicode(a, check):
458 def check_unicode(a, check):
459 assert isinstance(a, unicode), "%r is not unicode"%a
459 assert isinstance(a, unicode), "%r is not unicode"%a
460 assert isinstance(check, bytes), "%r is not bytes"%check
460 assert isinstance(check, bytes), "%r is not bytes"%check
461 assert a.encode('utf8') == check, "%s != %s"%(a,check)
461 assert a.encode('utf8') == check, "%s != %s"%(a,check)
462
462
463 for s in [ u'é', u'ßø®∫',u'asdf' ]:
463 for s in [ u'é', u'ßø®∫',u'asdf' ]:
464 try:
464 try:
465 v.apply_sync(check_unicode, s, s.encode('utf8'))
465 v.apply_sync(check_unicode, s, s.encode('utf8'))
466 except error.RemoteError as e:
466 except error.RemoteError as e:
467 if e.ename == 'AssertionError':
467 if e.ename == 'AssertionError':
468 self.fail(e.evalue)
468 self.fail(e.evalue)
469 else:
469 else:
470 raise e
470 raise e
471
471
472 def test_map_reference(self):
472 def test_map_reference(self):
473 """view.map(<Reference>, *seqs) should work"""
473 """view.map(<Reference>, *seqs) should work"""
474 v = self.client[:]
474 v = self.client[:]
475 v.scatter('n', self.client.ids, flatten=True)
475 v.scatter('n', self.client.ids, flatten=True)
476 v.execute("f = lambda x,y: x*y")
476 v.execute("f = lambda x,y: x*y")
477 rf = pmod.Reference('f')
477 rf = pmod.Reference('f')
478 nlist = list(range(10))
478 nlist = list(range(10))
479 mlist = nlist[::-1]
479 mlist = nlist[::-1]
480 expected = [ m*n for m,n in zip(mlist, nlist) ]
480 expected = [ m*n for m,n in zip(mlist, nlist) ]
481 result = v.map_sync(rf, mlist, nlist)
481 result = v.map_sync(rf, mlist, nlist)
482 self.assertEquals(result, expected)
482 self.assertEquals(result, expected)
483
483
484 def test_apply_reference(self):
484 def test_apply_reference(self):
485 """view.apply(<Reference>, *args) should work"""
485 """view.apply(<Reference>, *args) should work"""
486 v = self.client[:]
486 v = self.client[:]
487 v.scatter('n', self.client.ids, flatten=True)
487 v.scatter('n', self.client.ids, flatten=True)
488 v.execute("f = lambda x: n*x")
488 v.execute("f = lambda x: n*x")
489 rf = pmod.Reference('f')
489 rf = pmod.Reference('f')
490 result = v.apply_sync(rf, 5)
490 result = v.apply_sync(rf, 5)
491 expected = [ 5*id for id in self.client.ids ]
491 expected = [ 5*id for id in self.client.ids ]
492 self.assertEquals(result, expected)
492 self.assertEquals(result, expected)
493
494 def test_eval_reference(self):
495 v = self.client[self.client.ids[0]]
496 v['g'] = range(5)
497 rg = pmod.Reference('g[0]')
498 echo = lambda x:x
499 self.assertEquals(v.apply_sync(echo, rg), 0)
500
501 def test_reference_nameerror(self):
502 v = self.client[self.client.ids[0]]
503 r = pmod.Reference('elvis_has_left')
504 echo = lambda x:x
505 self.assertRaisesRemote(NameError, v.apply_sync, echo, r)
506
493
507
@@ -1,153 +1,151 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """Pickle related utilities. Perhaps this should be called 'can'."""
3 """Pickle related utilities. Perhaps this should be called 'can'."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008-2011 The IPython Development Team
8 # Copyright (C) 2008-2011 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import copy
18 import copy
19 import sys
19 import sys
20 from types import FunctionType
20 from types import FunctionType
21
21
22 import codeutil
22 import codeutil
23
23
24 #-------------------------------------------------------------------------------
24 #-------------------------------------------------------------------------------
25 # Classes
25 # Classes
26 #-------------------------------------------------------------------------------
26 #-------------------------------------------------------------------------------
27
27
28
28
29 class CannedObject(object):
29 class CannedObject(object):
30 def __init__(self, obj, keys=[]):
30 def __init__(self, obj, keys=[]):
31 self.keys = keys
31 self.keys = keys
32 self.obj = copy.copy(obj)
32 self.obj = copy.copy(obj)
33 for key in keys:
33 for key in keys:
34 setattr(self.obj, key, can(getattr(obj, key)))
34 setattr(self.obj, key, can(getattr(obj, key)))
35
35
36
36
37 def getObject(self, g=None):
37 def getObject(self, g=None):
38 if g is None:
38 if g is None:
39 g = globals()
39 g = globals()
40 for key in self.keys:
40 for key in self.keys:
41 setattr(self.obj, key, uncan(getattr(self.obj, key), g))
41 setattr(self.obj, key, uncan(getattr(self.obj, key), g))
42 return self.obj
42 return self.obj
43
43
44 class Reference(CannedObject):
44 class Reference(CannedObject):
45 """object for wrapping a remote reference by name."""
45 """object for wrapping a remote reference by name."""
46 def __init__(self, name):
46 def __init__(self, name):
47 if not isinstance(name, basestring):
47 if not isinstance(name, basestring):
48 raise TypeError("illegal name: %r"%name)
48 raise TypeError("illegal name: %r"%name)
49 self.name = name
49 self.name = name
50
50
51 def __repr__(self):
51 def __repr__(self):
52 return "<Reference: %r>"%self.name
52 return "<Reference: %r>"%self.name
53
53
54 def getObject(self, g=None):
54 def getObject(self, g=None):
55 if g is None:
55 if g is None:
56 g = globals()
56 g = globals()
57 try:
57
58 return g[self.name]
58 return eval(self.name, g)
59 except KeyError:
60 raise NameError("name %r is not defined"%self.name)
61
59
62
60
63 class CannedFunction(CannedObject):
61 class CannedFunction(CannedObject):
64
62
65 def __init__(self, f):
63 def __init__(self, f):
66 self._checkType(f)
64 self._checkType(f)
67 self.code = f.func_code
65 self.code = f.func_code
68 self.defaults = f.func_defaults
66 self.defaults = f.func_defaults
69 self.module = f.__module__ or '__main__'
67 self.module = f.__module__ or '__main__'
70 self.__name__ = f.__name__
68 self.__name__ = f.__name__
71
69
72 def _checkType(self, obj):
70 def _checkType(self, obj):
73 assert isinstance(obj, FunctionType), "Not a function type"
71 assert isinstance(obj, FunctionType), "Not a function type"
74
72
75 def getObject(self, g=None):
73 def getObject(self, g=None):
76 # try to load function back into its module:
74 # try to load function back into its module:
77 if not self.module.startswith('__'):
75 if not self.module.startswith('__'):
78 try:
76 try:
79 __import__(self.module)
77 __import__(self.module)
80 except ImportError:
78 except ImportError:
81 pass
79 pass
82 else:
80 else:
83 g = sys.modules[self.module].__dict__
81 g = sys.modules[self.module].__dict__
84
82
85 if g is None:
83 if g is None:
86 g = globals()
84 g = globals()
87 newFunc = FunctionType(self.code, g, self.__name__, self.defaults)
85 newFunc = FunctionType(self.code, g, self.__name__, self.defaults)
88 return newFunc
86 return newFunc
89
87
90 #-------------------------------------------------------------------------------
88 #-------------------------------------------------------------------------------
91 # Functions
89 # Functions
92 #-------------------------------------------------------------------------------
90 #-------------------------------------------------------------------------------
93
91
94 def can(obj):
92 def can(obj):
95 # import here to prevent module-level circular imports
93 # import here to prevent module-level circular imports
96 from IPython.parallel import dependent
94 from IPython.parallel import dependent
97 if isinstance(obj, dependent):
95 if isinstance(obj, dependent):
98 keys = ('f','df')
96 keys = ('f','df')
99 return CannedObject(obj, keys=keys)
97 return CannedObject(obj, keys=keys)
100 elif isinstance(obj, FunctionType):
98 elif isinstance(obj, FunctionType):
101 return CannedFunction(obj)
99 return CannedFunction(obj)
102 elif isinstance(obj,dict):
100 elif isinstance(obj,dict):
103 return canDict(obj)
101 return canDict(obj)
104 elif isinstance(obj, (list,tuple)):
102 elif isinstance(obj, (list,tuple)):
105 return canSequence(obj)
103 return canSequence(obj)
106 else:
104 else:
107 return obj
105 return obj
108
106
109 def canDict(obj):
107 def canDict(obj):
110 if isinstance(obj, dict):
108 if isinstance(obj, dict):
111 newobj = {}
109 newobj = {}
112 for k, v in obj.iteritems():
110 for k, v in obj.iteritems():
113 newobj[k] = can(v)
111 newobj[k] = can(v)
114 return newobj
112 return newobj
115 else:
113 else:
116 return obj
114 return obj
117
115
118 def canSequence(obj):
116 def canSequence(obj):
119 if isinstance(obj, (list, tuple)):
117 if isinstance(obj, (list, tuple)):
120 t = type(obj)
118 t = type(obj)
121 return t([can(i) for i in obj])
119 return t([can(i) for i in obj])
122 else:
120 else:
123 return obj
121 return obj
124
122
125 def uncan(obj, g=None):
123 def uncan(obj, g=None):
126 if isinstance(obj, CannedObject):
124 if isinstance(obj, CannedObject):
127 return obj.getObject(g)
125 return obj.getObject(g)
128 elif isinstance(obj,dict):
126 elif isinstance(obj,dict):
129 return uncanDict(obj, g)
127 return uncanDict(obj, g)
130 elif isinstance(obj, (list,tuple)):
128 elif isinstance(obj, (list,tuple)):
131 return uncanSequence(obj, g)
129 return uncanSequence(obj, g)
132 else:
130 else:
133 return obj
131 return obj
134
132
135 def uncanDict(obj, g=None):
133 def uncanDict(obj, g=None):
136 if isinstance(obj, dict):
134 if isinstance(obj, dict):
137 newobj = {}
135 newobj = {}
138 for k, v in obj.iteritems():
136 for k, v in obj.iteritems():
139 newobj[k] = uncan(v,g)
137 newobj[k] = uncan(v,g)
140 return newobj
138 return newobj
141 else:
139 else:
142 return obj
140 return obj
143
141
144 def uncanSequence(obj, g=None):
142 def uncanSequence(obj, g=None):
145 if isinstance(obj, (list, tuple)):
143 if isinstance(obj, (list, tuple)):
146 t = type(obj)
144 t = type(obj)
147 return t([uncan(i,g) for i in obj])
145 return t([uncan(i,g) for i in obj])
148 else:
146 else:
149 return obj
147 return obj
150
148
151
149
152 def rebindFunctionGlobals(f, glbls):
150 def rebindFunctionGlobals(f, glbls):
153 return FunctionType(f.func_code, glbls)
151 return FunctionType(f.func_code, glbls)
General Comments 0
You need to be logged in to leave comments. Login now