##// END OF EJS Templates
clean up imports
Paul Ivanov -
Show More
@@ -1,96 +1,95 b''
1 """Tests for input manipulation machinery."""
1 """Tests for input manipulation machinery."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Imports
4 # Imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 import nose.tools as nt
6 import nose.tools as nt
7
7
8 from IPython.core.prefilter import AutocallChecker
8 from IPython.core.prefilter import AutocallChecker
9 from IPython.testing import decorators as dec
10 from IPython.testing.globalipapp import get_ipython
9 from IPython.testing.globalipapp import get_ipython
11
10
12 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
13 # Tests
12 # Tests
14 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
15 ip = get_ipython()
14 ip = get_ipython()
16
15
17 def test_prefilter():
16 def test_prefilter():
18 """Test user input conversions"""
17 """Test user input conversions"""
19
18
20 # pairs of (raw, expected correct) input
19 # pairs of (raw, expected correct) input
21 pairs = [ ('2+2','2+2'),
20 pairs = [ ('2+2','2+2'),
22 ]
21 ]
23
22
24 for raw, correct in pairs:
23 for raw, correct in pairs:
25 nt.assert_equal(ip.prefilter(raw), correct)
24 nt.assert_equal(ip.prefilter(raw), correct)
26
25
27
26
28 def test_autocall_binops():
27 def test_autocall_binops():
29 """See https://github.com/ipython/ipython/issues/81"""
28 """See https://github.com/ipython/ipython/issues/81"""
30 ip.magic('autocall 2')
29 ip.magic('autocall 2')
31 f = lambda x: x
30 f = lambda x: x
32 ip.user_ns['f'] = f
31 ip.user_ns['f'] = f
33 try:
32 try:
34 nt.assert_equal(ip.prefilter('f 1'),'f(1)')
33 nt.assert_equal(ip.prefilter('f 1'),'f(1)')
35 for t in ['f +1', 'f -1']:
34 for t in ['f +1', 'f -1']:
36 nt.assert_equal(ip.prefilter(t), t)
35 nt.assert_equal(ip.prefilter(t), t)
37
36
38 # Run tests again with a more permissive exclude_regexp, which will
37 # Run tests again with a more permissive exclude_regexp, which will
39 # allow transformation of binary operations ('f -1' -> 'f(-1)').
38 # allow transformation of binary operations ('f -1' -> 'f(-1)').
40 pm = ip.prefilter_manager
39 pm = ip.prefilter_manager
41 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
40 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
42 config=pm.config)
41 config=pm.config)
43 try:
42 try:
44 ac.priority = 1
43 ac.priority = 1
45 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
44 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
46 pm.sort_checkers()
45 pm.sort_checkers()
47
46
48 nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
47 nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
49 nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
48 nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
50 finally:
49 finally:
51 pm.unregister_checker(ac)
50 pm.unregister_checker(ac)
52 finally:
51 finally:
53 ip.magic('autocall 0')
52 ip.magic('autocall 0')
54 del ip.user_ns['f']
53 del ip.user_ns['f']
55
54
56
55
57 def test_issue_114():
56 def test_issue_114():
58 """Check that multiline string literals don't expand as magic
57 """Check that multiline string literals don't expand as magic
59 see http://github.com/ipython/ipython/issues/114"""
58 see http://github.com/ipython/ipython/issues/114"""
60
59
61 template = '"""\n%s\n"""'
60 template = '"""\n%s\n"""'
62 # Store the current value of multi_line_specials and turn it off before
61 # Store the current value of multi_line_specials and turn it off before
63 # running test, since it could be true (case in which the test doesn't make
62 # running test, since it could be true (case in which the test doesn't make
64 # sense, as multiline string literals *will* expand as magic in that case).
63 # sense, as multiline string literals *will* expand as magic in that case).
65 msp = ip.prefilter_manager.multi_line_specials
64 msp = ip.prefilter_manager.multi_line_specials
66 ip.prefilter_manager.multi_line_specials = False
65 ip.prefilter_manager.multi_line_specials = False
67 try:
66 try:
68 for mgk in ip.magics_manager.lsmagic()['line']:
67 for mgk in ip.magics_manager.lsmagic()['line']:
69 raw = template % mgk
68 raw = template % mgk
70 nt.assert_equal(ip.prefilter(raw), raw)
69 nt.assert_equal(ip.prefilter(raw), raw)
71 finally:
70 finally:
72 ip.prefilter_manager.multi_line_specials = msp
71 ip.prefilter_manager.multi_line_specials = msp
73
72
74
73
75 def test_prefilter_attribute_errors():
74 def test_prefilter_attribute_errors():
76 """Capture exceptions thrown by user objects on attribute access.
75 """Capture exceptions thrown by user objects on attribute access.
77
76
78 See http://github.com/ipython/ipython/issues/988."""
77 See http://github.com/ipython/ipython/issues/988."""
79
78
80 class X(object):
79 class X(object):
81 def __getattr__(self, k):
80 def __getattr__(self, k):
82 raise ValueError('broken object')
81 raise ValueError('broken object')
83 def __call__(self, x):
82 def __call__(self, x):
84 return x
83 return x
85
84
86 # Create a callable broken object
85 # Create a callable broken object
87 ip.user_ns['x'] = X()
86 ip.user_ns['x'] = X()
88 ip.magic('autocall 2')
87 ip.magic('autocall 2')
89 try:
88 try:
90 # Even if x throws an attribute error when looking at its rewrite
89 # Even if x throws an attribute error when looking at its rewrite
91 # attribute, we should not crash. So the test here is simply making
90 # attribute, we should not crash. So the test here is simply making
92 # the prefilter call and not having an exception.
91 # the prefilter call and not having an exception.
93 ip.prefilter('x 1')
92 ip.prefilter('x 1')
94 finally:
93 finally:
95 del ip.user_ns['x']
94 del ip.user_ns['x']
96 ip.magic('autocall 0')
95 ip.magic('autocall 0')
@@ -1,59 +1,58 b''
1 """Tests for kernel utility functions
1 """Tests for kernel utility functions
2
2
3 Authors
3 Authors
4 -------
4 -------
5 * MinRK
5 * MinRK
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2011, the IPython Development Team.
8 # Copyright (c) 2011, the IPython Development Team.
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # Third-party imports
19 # Third-party imports
20 import nose.tools as nt
20 import nose.tools as nt
21
21
22 # Our own imports
22 # Our own imports
23 from IPython.testing import decorators as dec
24 from IPython.kernel.launcher import swallow_argv
23 from IPython.kernel.launcher import swallow_argv
25
24
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
27 # Classes and functions
26 # Classes and functions
28 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
29
28
30 def test_swallow_argv():
29 def test_swallow_argv():
31 tests = [
30 tests = [
32 # expected , argv , aliases, flags
31 # expected , argv , aliases, flags
33 (['-a', '5'], ['-a', '5'], None, None),
32 (['-a', '5'], ['-a', '5'], None, None),
34 (['5'], ['-a', '5'], None, ['a']),
33 (['5'], ['-a', '5'], None, ['a']),
35 ([], ['-a', '5'], ['a'], None),
34 ([], ['-a', '5'], ['a'], None),
36 ([], ['-a', '5'], ['a'], ['a']),
35 ([], ['-a', '5'], ['a'], ['a']),
37 ([], ['--foo'], None, ['foo']),
36 ([], ['--foo'], None, ['foo']),
38 ([], ['--foo'], ['foobar'], []),
37 ([], ['--foo'], ['foobar'], []),
39 ([], ['--foo', '5'], ['foo'], []),
38 ([], ['--foo', '5'], ['foo'], []),
40 ([], ['--foo=5'], ['foo'], []),
39 ([], ['--foo=5'], ['foo'], []),
41 (['--foo=5'], ['--foo=5'], [], ['foo']),
40 (['--foo=5'], ['--foo=5'], [], ['foo']),
42 (['5'], ['--foo', '5'], [], ['foo']),
41 (['5'], ['--foo', '5'], [], ['foo']),
43 (['bar'], ['--foo', '5', 'bar'], ['foo'], ['foo']),
42 (['bar'], ['--foo', '5', 'bar'], ['foo'], ['foo']),
44 (['bar'], ['--foo=5', 'bar'], ['foo'], ['foo']),
43 (['bar'], ['--foo=5', 'bar'], ['foo'], ['foo']),
45 (['5','bar'], ['--foo', '5', 'bar'], None, ['foo']),
44 (['5','bar'], ['--foo', '5', 'bar'], None, ['foo']),
46 (['bar'], ['--foo', '5', 'bar'], ['foo'], None),
45 (['bar'], ['--foo', '5', 'bar'], ['foo'], None),
47 (['bar'], ['--foo=5', 'bar'], ['foo'], None),
46 (['bar'], ['--foo=5', 'bar'], ['foo'], None),
48 ]
47 ]
49 for expected, argv, aliases, flags in tests:
48 for expected, argv, aliases, flags in tests:
50 stripped = swallow_argv(argv, aliases=aliases, flags=flags)
49 stripped = swallow_argv(argv, aliases=aliases, flags=flags)
51 message = '\n'.join(['',
50 message = '\n'.join(['',
52 "argv: %r" % argv,
51 "argv: %r" % argv,
53 "aliases: %r" % aliases,
52 "aliases: %r" % aliases,
54 "flags : %r" % flags,
53 "flags : %r" % flags,
55 "expected : %r" % expected,
54 "expected : %r" % expected,
56 "returned : %r" % stripped,
55 "returned : %r" % stripped,
57 ])
56 ])
58 nt.assert_equal(expected, stripped, message)
57 nt.assert_equal(expected, stripped, message)
59
58
@@ -1,128 +1,127 b''
1 """
1 """
2 Module with tests for Strings
2 Module with tests for Strings
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 import os
16 import os
17
17
18 from IPython.testing import decorators as dec
19 from ...tests.base import TestsBase
18 from ...tests.base import TestsBase
20 from ..strings import (wrap_text, html2text, add_anchor, strip_dollars,
19 from ..strings import (wrap_text, html2text, add_anchor, strip_dollars,
21 strip_files_prefix, get_lines, comment_lines, ipython2python, posix_path,
20 strip_files_prefix, get_lines, comment_lines, ipython2python, posix_path,
22 )
21 )
23
22
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Class
25 # Class
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 class TestStrings(TestsBase):
28 class TestStrings(TestsBase):
30
29
31 def test_wrap_text(self):
30 def test_wrap_text(self):
32 """wrap_text test"""
31 """wrap_text test"""
33 test_text = """
32 test_text = """
34 Tush! never tell me; I take it much unkindly
33 Tush! never tell me; I take it much unkindly
35 That thou, Iago, who hast had my purse
34 That thou, Iago, who hast had my purse
36 As if the strings were thine, shouldst know of this.
35 As if the strings were thine, shouldst know of this.
37 """
36 """
38 for length in [30,5,1]:
37 for length in [30,5,1]:
39 self._confirm_wrap_text(test_text, length)
38 self._confirm_wrap_text(test_text, length)
40
39
41
40
42 def _confirm_wrap_text(self, text, length):
41 def _confirm_wrap_text(self, text, length):
43 for line in wrap_text(text, length).split('\n'):
42 for line in wrap_text(text, length).split('\n'):
44 assert len(line) <= length
43 assert len(line) <= length
45
44
46
45
47 def test_html2text(self):
46 def test_html2text(self):
48 """html2text test"""
47 """html2text test"""
49 #TODO: More tests
48 #TODO: More tests
50 self.assertEqual(html2text('<name>joe</name>'), 'joe')
49 self.assertEqual(html2text('<name>joe</name>'), 'joe')
51
50
52
51
53 def test_add_anchor(self):
52 def test_add_anchor(self):
54 """add_anchor test"""
53 """add_anchor test"""
55 #TODO: More tests
54 #TODO: More tests
56 results = add_anchor('<b>Hello World!</b>')
55 results = add_anchor('<b>Hello World!</b>')
57 assert 'Hello World!' in results
56 assert 'Hello World!' in results
58 assert 'id="' in results
57 assert 'id="' in results
59 assert 'class="anchor-link"' in results
58 assert 'class="anchor-link"' in results
60 assert '<b' in results
59 assert '<b' in results
61 assert '</b>' in results
60 assert '</b>' in results
62
61
63
62
64 def test_strip_dollars(self):
63 def test_strip_dollars(self):
65 """strip_dollars test"""
64 """strip_dollars test"""
66 tests = [
65 tests = [
67 ('', ''),
66 ('', ''),
68 ('$$', ''),
67 ('$$', ''),
69 ('$H$', 'H'),
68 ('$H$', 'H'),
70 ('$He', 'He'),
69 ('$He', 'He'),
71 ('H$el', 'H$el'),
70 ('H$el', 'H$el'),
72 ('Hell$', 'Hell'),
71 ('Hell$', 'Hell'),
73 ('Hello', 'Hello'),
72 ('Hello', 'Hello'),
74 ('W$o$rld', 'W$o$rld')]
73 ('W$o$rld', 'W$o$rld')]
75 for test in tests:
74 for test in tests:
76 self._try_strip_dollars(test[0], test[1])
75 self._try_strip_dollars(test[0], test[1])
77
76
78
77
79 def _try_strip_dollars(self, test, result):
78 def _try_strip_dollars(self, test, result):
80 self.assertEqual(strip_dollars(test), result)
79 self.assertEqual(strip_dollars(test), result)
81
80
82
81
83 def test_strip_files_prefix(self):
82 def test_strip_files_prefix(self):
84 """strip_files_prefix test"""
83 """strip_files_prefix test"""
85 tests = [
84 tests = [
86 ('', ''),
85 ('', ''),
87 ('/files', '/files'),
86 ('/files', '/files'),
88 ('test="/files"', 'test="/files"'),
87 ('test="/files"', 'test="/files"'),
89 ('My files are in `files/`', 'My files are in `files/`'),
88 ('My files are in `files/`', 'My files are in `files/`'),
90 ('<a href="files/test.html">files/test.html</a>', '<a href="test.html">files/test.html</a>')]
89 ('<a href="files/test.html">files/test.html</a>', '<a href="test.html">files/test.html</a>')]
91 for test in tests:
90 for test in tests:
92 self._try_files_prefix(test[0], test[1])
91 self._try_files_prefix(test[0], test[1])
93
92
94
93
95 def _try_files_prefix(self, test, result):
94 def _try_files_prefix(self, test, result):
96 self.assertEqual(strip_files_prefix(test), result)
95 self.assertEqual(strip_files_prefix(test), result)
97
96
98
97
99 def test_comment_lines(self):
98 def test_comment_lines(self):
100 """comment_lines test"""
99 """comment_lines test"""
101 for line in comment_lines('hello\nworld\n!').split('\n'):
100 for line in comment_lines('hello\nworld\n!').split('\n'):
102 assert line.startswith('# ')
101 assert line.startswith('# ')
103 for line in comment_lines('hello\nworld\n!', 'beep').split('\n'):
102 for line in comment_lines('hello\nworld\n!', 'beep').split('\n'):
104 assert line.startswith('beep')
103 assert line.startswith('beep')
105
104
106
105
107 def test_get_lines(self):
106 def test_get_lines(self):
108 """get_lines test"""
107 """get_lines test"""
109 text = "hello\nworld\n!"
108 text = "hello\nworld\n!"
110 self.assertEqual(get_lines(text, start=1), "world\n!")
109 self.assertEqual(get_lines(text, start=1), "world\n!")
111 self.assertEqual(get_lines(text, end=2), "hello\nworld")
110 self.assertEqual(get_lines(text, end=2), "hello\nworld")
112 self.assertEqual(get_lines(text, start=2, end=5), "!")
111 self.assertEqual(get_lines(text, start=2, end=5), "!")
113 self.assertEqual(get_lines(text, start=-2), "world\n!")
112 self.assertEqual(get_lines(text, start=-2), "world\n!")
114
113
115
114
116 def test_ipython2python(self):
115 def test_ipython2python(self):
117 """ipython2python test"""
116 """ipython2python test"""
118 #TODO: More tests
117 #TODO: More tests
119 results = ipython2python(u'%%pylab\nprint("Hello-World")').replace("u'", "'")
118 results = ipython2python(u'%%pylab\nprint("Hello-World")').replace("u'", "'")
120 self.fuzzy_compare(results, u"get_ipython().run_cell_magic('pylab', '', 'print(\"Hello-World\")')",
119 self.fuzzy_compare(results, u"get_ipython().run_cell_magic('pylab', '', 'print(\"Hello-World\")')",
121 ignore_spaces=True, ignore_newlines=True)
120 ignore_spaces=True, ignore_newlines=True)
122
121
123 def test_posix_path(self):
122 def test_posix_path(self):
124 path_list = ['foo', 'bar']
123 path_list = ['foo', 'bar']
125 expected = '/'.join(path_list)
124 expected = '/'.join(path_list)
126 native = os.path.join(*path_list)
125 native = os.path.join(*path_list)
127 filtered = posix_path(native)
126 filtered = posix_path(native)
128 self.assertEqual(filtered, expected)
127 self.assertEqual(filtered, expected)
@@ -1,379 +1,374 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Test Parallel magics
2 """Test Parallel magics
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 re
19 import re
20 import sys
21 import time
20 import time
22
21
23 import zmq
24 from nose import SkipTest
25
22
26 from IPython.testing import decorators as dec
23 from IPython.testing import decorators as dec
27 from IPython.utils.io import capture_output
24 from IPython.utils.io import capture_output
28
25
29 from IPython import parallel as pmod
26 from IPython import parallel as pmod
30 from IPython.parallel import error
31 from IPython.parallel import AsyncResult
27 from IPython.parallel import AsyncResult
32 from IPython.parallel.util import interactive
33
28
34 from IPython.parallel.tests import add_engines
29 from IPython.parallel.tests import add_engines
35
30
36 from .clienttest import ClusterTestCase, generate_output
31 from .clienttest import ClusterTestCase, generate_output
37
32
38 def setup():
33 def setup():
39 add_engines(3, total=True)
34 add_engines(3, total=True)
40
35
41 class TestParallelMagics(ClusterTestCase):
36 class TestParallelMagics(ClusterTestCase):
42
37
43 def test_px_blocking(self):
38 def test_px_blocking(self):
44 ip = get_ipython()
39 ip = get_ipython()
45 v = self.client[-1:]
40 v = self.client[-1:]
46 v.activate()
41 v.activate()
47 v.block=True
42 v.block=True
48
43
49 ip.magic('px a=5')
44 ip.magic('px a=5')
50 self.assertEqual(v['a'], [5])
45 self.assertEqual(v['a'], [5])
51 ip.magic('px a=10')
46 ip.magic('px a=10')
52 self.assertEqual(v['a'], [10])
47 self.assertEqual(v['a'], [10])
53 # just 'print a' works ~99% of the time, but this ensures that
48 # just 'print a' works ~99% of the time, but this ensures that
54 # the stdout message has arrived when the result is finished:
49 # the stdout message has arrived when the result is finished:
55 with capture_output() as io:
50 with capture_output() as io:
56 ip.magic(
51 ip.magic(
57 'px import sys,time;print(a);sys.stdout.flush();time.sleep(0.2)'
52 'px import sys,time;print(a);sys.stdout.flush();time.sleep(0.2)'
58 )
53 )
59 self.assertIn('[stdout:', io.stdout)
54 self.assertIn('[stdout:', io.stdout)
60 self.assertNotIn('\n\n', io.stdout)
55 self.assertNotIn('\n\n', io.stdout)
61 assert io.stdout.rstrip().endswith('10')
56 assert io.stdout.rstrip().endswith('10')
62 self.assertRaisesRemote(ZeroDivisionError, ip.magic, 'px 1/0')
57 self.assertRaisesRemote(ZeroDivisionError, ip.magic, 'px 1/0')
63
58
64 def _check_generated_stderr(self, stderr, n):
59 def _check_generated_stderr(self, stderr, n):
65 expected = [
60 expected = [
66 r'\[stderr:\d+\]',
61 r'\[stderr:\d+\]',
67 '^stderr$',
62 '^stderr$',
68 '^stderr2$',
63 '^stderr2$',
69 ] * n
64 ] * n
70
65
71 self.assertNotIn('\n\n', stderr)
66 self.assertNotIn('\n\n', stderr)
72 lines = stderr.splitlines()
67 lines = stderr.splitlines()
73 self.assertEqual(len(lines), len(expected), stderr)
68 self.assertEqual(len(lines), len(expected), stderr)
74 for line,expect in zip(lines, expected):
69 for line,expect in zip(lines, expected):
75 if isinstance(expect, str):
70 if isinstance(expect, str):
76 expect = [expect]
71 expect = [expect]
77 for ex in expect:
72 for ex in expect:
78 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
73 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
79
74
80 def test_cellpx_block_args(self):
75 def test_cellpx_block_args(self):
81 """%%px --[no]block flags work"""
76 """%%px --[no]block flags work"""
82 ip = get_ipython()
77 ip = get_ipython()
83 v = self.client[-1:]
78 v = self.client[-1:]
84 v.activate()
79 v.activate()
85 v.block=False
80 v.block=False
86
81
87 for block in (True, False):
82 for block in (True, False):
88 v.block = block
83 v.block = block
89 ip.magic("pxconfig --verbose")
84 ip.magic("pxconfig --verbose")
90 with capture_output(display=False) as io:
85 with capture_output(display=False) as io:
91 ip.run_cell_magic("px", "", "1")
86 ip.run_cell_magic("px", "", "1")
92 if block:
87 if block:
93 assert io.stdout.startswith("Parallel"), io.stdout
88 assert io.stdout.startswith("Parallel"), io.stdout
94 else:
89 else:
95 assert io.stdout.startswith("Async"), io.stdout
90 assert io.stdout.startswith("Async"), io.stdout
96
91
97 with capture_output(display=False) as io:
92 with capture_output(display=False) as io:
98 ip.run_cell_magic("px", "--block", "1")
93 ip.run_cell_magic("px", "--block", "1")
99 assert io.stdout.startswith("Parallel"), io.stdout
94 assert io.stdout.startswith("Parallel"), io.stdout
100
95
101 with capture_output(display=False) as io:
96 with capture_output(display=False) as io:
102 ip.run_cell_magic("px", "--noblock", "1")
97 ip.run_cell_magic("px", "--noblock", "1")
103 assert io.stdout.startswith("Async"), io.stdout
98 assert io.stdout.startswith("Async"), io.stdout
104
99
105 def test_cellpx_groupby_engine(self):
100 def test_cellpx_groupby_engine(self):
106 """%%px --group-outputs=engine"""
101 """%%px --group-outputs=engine"""
107 ip = get_ipython()
102 ip = get_ipython()
108 v = self.client[:]
103 v = self.client[:]
109 v.block = True
104 v.block = True
110 v.activate()
105 v.activate()
111
106
112 v['generate_output'] = generate_output
107 v['generate_output'] = generate_output
113
108
114 with capture_output(display=False) as io:
109 with capture_output(display=False) as io:
115 ip.run_cell_magic('px', '--group-outputs=engine', 'generate_output()')
110 ip.run_cell_magic('px', '--group-outputs=engine', 'generate_output()')
116
111
117 self.assertNotIn('\n\n', io.stdout)
112 self.assertNotIn('\n\n', io.stdout)
118 lines = io.stdout.splitlines()
113 lines = io.stdout.splitlines()
119 expected = [
114 expected = [
120 r'\[stdout:\d+\]',
115 r'\[stdout:\d+\]',
121 'stdout',
116 'stdout',
122 'stdout2',
117 'stdout2',
123 r'\[output:\d+\]',
118 r'\[output:\d+\]',
124 r'IPython\.core\.display\.HTML',
119 r'IPython\.core\.display\.HTML',
125 r'IPython\.core\.display\.Math',
120 r'IPython\.core\.display\.Math',
126 r'Out\[\d+:\d+\]:.*IPython\.core\.display\.Math',
121 r'Out\[\d+:\d+\]:.*IPython\.core\.display\.Math',
127 ] * len(v)
122 ] * len(v)
128
123
129 self.assertEqual(len(lines), len(expected), io.stdout)
124 self.assertEqual(len(lines), len(expected), io.stdout)
130 for line,expect in zip(lines, expected):
125 for line,expect in zip(lines, expected):
131 if isinstance(expect, str):
126 if isinstance(expect, str):
132 expect = [expect]
127 expect = [expect]
133 for ex in expect:
128 for ex in expect:
134 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
129 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
135
130
136 self._check_generated_stderr(io.stderr, len(v))
131 self._check_generated_stderr(io.stderr, len(v))
137
132
138
133
139 def test_cellpx_groupby_order(self):
134 def test_cellpx_groupby_order(self):
140 """%%px --group-outputs=order"""
135 """%%px --group-outputs=order"""
141 ip = get_ipython()
136 ip = get_ipython()
142 v = self.client[:]
137 v = self.client[:]
143 v.block = True
138 v.block = True
144 v.activate()
139 v.activate()
145
140
146 v['generate_output'] = generate_output
141 v['generate_output'] = generate_output
147
142
148 with capture_output(display=False) as io:
143 with capture_output(display=False) as io:
149 ip.run_cell_magic('px', '--group-outputs=order', 'generate_output()')
144 ip.run_cell_magic('px', '--group-outputs=order', 'generate_output()')
150
145
151 self.assertNotIn('\n\n', io.stdout)
146 self.assertNotIn('\n\n', io.stdout)
152 lines = io.stdout.splitlines()
147 lines = io.stdout.splitlines()
153 expected = []
148 expected = []
154 expected.extend([
149 expected.extend([
155 r'\[stdout:\d+\]',
150 r'\[stdout:\d+\]',
156 'stdout',
151 'stdout',
157 'stdout2',
152 'stdout2',
158 ] * len(v))
153 ] * len(v))
159 expected.extend([
154 expected.extend([
160 r'\[output:\d+\]',
155 r'\[output:\d+\]',
161 'IPython.core.display.HTML',
156 'IPython.core.display.HTML',
162 ] * len(v))
157 ] * len(v))
163 expected.extend([
158 expected.extend([
164 r'\[output:\d+\]',
159 r'\[output:\d+\]',
165 'IPython.core.display.Math',
160 'IPython.core.display.Math',
166 ] * len(v))
161 ] * len(v))
167 expected.extend([
162 expected.extend([
168 r'Out\[\d+:\d+\]:.*IPython\.core\.display\.Math'
163 r'Out\[\d+:\d+\]:.*IPython\.core\.display\.Math'
169 ] * len(v))
164 ] * len(v))
170
165
171 self.assertEqual(len(lines), len(expected), io.stdout)
166 self.assertEqual(len(lines), len(expected), io.stdout)
172 for line,expect in zip(lines, expected):
167 for line,expect in zip(lines, expected):
173 if isinstance(expect, str):
168 if isinstance(expect, str):
174 expect = [expect]
169 expect = [expect]
175 for ex in expect:
170 for ex in expect:
176 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
171 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
177
172
178 self._check_generated_stderr(io.stderr, len(v))
173 self._check_generated_stderr(io.stderr, len(v))
179
174
180 def test_cellpx_groupby_type(self):
175 def test_cellpx_groupby_type(self):
181 """%%px --group-outputs=type"""
176 """%%px --group-outputs=type"""
182 ip = get_ipython()
177 ip = get_ipython()
183 v = self.client[:]
178 v = self.client[:]
184 v.block = True
179 v.block = True
185 v.activate()
180 v.activate()
186
181
187 v['generate_output'] = generate_output
182 v['generate_output'] = generate_output
188
183
189 with capture_output(display=False) as io:
184 with capture_output(display=False) as io:
190 ip.run_cell_magic('px', '--group-outputs=type', 'generate_output()')
185 ip.run_cell_magic('px', '--group-outputs=type', 'generate_output()')
191
186
192 self.assertNotIn('\n\n', io.stdout)
187 self.assertNotIn('\n\n', io.stdout)
193 lines = io.stdout.splitlines()
188 lines = io.stdout.splitlines()
194
189
195 expected = []
190 expected = []
196 expected.extend([
191 expected.extend([
197 r'\[stdout:\d+\]',
192 r'\[stdout:\d+\]',
198 'stdout',
193 'stdout',
199 'stdout2',
194 'stdout2',
200 ] * len(v))
195 ] * len(v))
201 expected.extend([
196 expected.extend([
202 r'\[output:\d+\]',
197 r'\[output:\d+\]',
203 r'IPython\.core\.display\.HTML',
198 r'IPython\.core\.display\.HTML',
204 r'IPython\.core\.display\.Math',
199 r'IPython\.core\.display\.Math',
205 ] * len(v))
200 ] * len(v))
206 expected.extend([
201 expected.extend([
207 (r'Out\[\d+:\d+\]', r'IPython\.core\.display\.Math')
202 (r'Out\[\d+:\d+\]', r'IPython\.core\.display\.Math')
208 ] * len(v))
203 ] * len(v))
209
204
210 self.assertEqual(len(lines), len(expected), io.stdout)
205 self.assertEqual(len(lines), len(expected), io.stdout)
211 for line,expect in zip(lines, expected):
206 for line,expect in zip(lines, expected):
212 if isinstance(expect, str):
207 if isinstance(expect, str):
213 expect = [expect]
208 expect = [expect]
214 for ex in expect:
209 for ex in expect:
215 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
210 assert re.search(ex, line) is not None, "Expected %r in %r" % (ex, line)
216
211
217 self._check_generated_stderr(io.stderr, len(v))
212 self._check_generated_stderr(io.stderr, len(v))
218
213
219
214
220 def test_px_nonblocking(self):
215 def test_px_nonblocking(self):
221 ip = get_ipython()
216 ip = get_ipython()
222 v = self.client[-1:]
217 v = self.client[-1:]
223 v.activate()
218 v.activate()
224 v.block=False
219 v.block=False
225
220
226 ip.magic('px a=5')
221 ip.magic('px a=5')
227 self.assertEqual(v['a'], [5])
222 self.assertEqual(v['a'], [5])
228 ip.magic('px a=10')
223 ip.magic('px a=10')
229 self.assertEqual(v['a'], [10])
224 self.assertEqual(v['a'], [10])
230 ip.magic('pxconfig --verbose')
225 ip.magic('pxconfig --verbose')
231 with capture_output() as io:
226 with capture_output() as io:
232 ar = ip.magic('px print (a)')
227 ar = ip.magic('px print (a)')
233 self.assertIsInstance(ar, AsyncResult)
228 self.assertIsInstance(ar, AsyncResult)
234 self.assertIn('Async', io.stdout)
229 self.assertIn('Async', io.stdout)
235 self.assertNotIn('[stdout:', io.stdout)
230 self.assertNotIn('[stdout:', io.stdout)
236 self.assertNotIn('\n\n', io.stdout)
231 self.assertNotIn('\n\n', io.stdout)
237
232
238 ar = ip.magic('px 1/0')
233 ar = ip.magic('px 1/0')
239 self.assertRaisesRemote(ZeroDivisionError, ar.get)
234 self.assertRaisesRemote(ZeroDivisionError, ar.get)
240
235
241 def test_autopx_blocking(self):
236 def test_autopx_blocking(self):
242 ip = get_ipython()
237 ip = get_ipython()
243 v = self.client[-1]
238 v = self.client[-1]
244 v.activate()
239 v.activate()
245 v.block=True
240 v.block=True
246
241
247 with capture_output(display=False) as io:
242 with capture_output(display=False) as io:
248 ip.magic('autopx')
243 ip.magic('autopx')
249 ip.run_cell('\n'.join(('a=5','b=12345','c=0')))
244 ip.run_cell('\n'.join(('a=5','b=12345','c=0')))
250 ip.run_cell('b*=2')
245 ip.run_cell('b*=2')
251 ip.run_cell('print (b)')
246 ip.run_cell('print (b)')
252 ip.run_cell('b')
247 ip.run_cell('b')
253 ip.run_cell("b/c")
248 ip.run_cell("b/c")
254 ip.magic('autopx')
249 ip.magic('autopx')
255
250
256 output = io.stdout
251 output = io.stdout
257
252
258 assert output.startswith('%autopx enabled'), output
253 assert output.startswith('%autopx enabled'), output
259 assert output.rstrip().endswith('%autopx disabled'), output
254 assert output.rstrip().endswith('%autopx disabled'), output
260 self.assertIn('ZeroDivisionError', output)
255 self.assertIn('ZeroDivisionError', output)
261 self.assertIn('\nOut[', output)
256 self.assertIn('\nOut[', output)
262 self.assertIn(': 24690', output)
257 self.assertIn(': 24690', output)
263 ar = v.get_result(-1)
258 ar = v.get_result(-1)
264 self.assertEqual(v['a'], 5)
259 self.assertEqual(v['a'], 5)
265 self.assertEqual(v['b'], 24690)
260 self.assertEqual(v['b'], 24690)
266 self.assertRaisesRemote(ZeroDivisionError, ar.get)
261 self.assertRaisesRemote(ZeroDivisionError, ar.get)
267
262
268 def test_autopx_nonblocking(self):
263 def test_autopx_nonblocking(self):
269 ip = get_ipython()
264 ip = get_ipython()
270 v = self.client[-1]
265 v = self.client[-1]
271 v.activate()
266 v.activate()
272 v.block=False
267 v.block=False
273
268
274 with capture_output() as io:
269 with capture_output() as io:
275 ip.magic('autopx')
270 ip.magic('autopx')
276 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
271 ip.run_cell('\n'.join(('a=5','b=10','c=0')))
277 ip.run_cell('print (b)')
272 ip.run_cell('print (b)')
278 ip.run_cell('import time; time.sleep(0.1)')
273 ip.run_cell('import time; time.sleep(0.1)')
279 ip.run_cell("b/c")
274 ip.run_cell("b/c")
280 ip.run_cell('b*=2')
275 ip.run_cell('b*=2')
281 ip.magic('autopx')
276 ip.magic('autopx')
282
277
283 output = io.stdout.rstrip()
278 output = io.stdout.rstrip()
284
279
285 assert output.startswith('%autopx enabled'), output
280 assert output.startswith('%autopx enabled'), output
286 assert output.endswith('%autopx disabled'), output
281 assert output.endswith('%autopx disabled'), output
287 self.assertNotIn('ZeroDivisionError', output)
282 self.assertNotIn('ZeroDivisionError', output)
288 ar = v.get_result(-2)
283 ar = v.get_result(-2)
289 self.assertRaisesRemote(ZeroDivisionError, ar.get)
284 self.assertRaisesRemote(ZeroDivisionError, ar.get)
290 # prevent TaskAborted on pulls, due to ZeroDivisionError
285 # prevent TaskAborted on pulls, due to ZeroDivisionError
291 time.sleep(0.5)
286 time.sleep(0.5)
292 self.assertEqual(v['a'], 5)
287 self.assertEqual(v['a'], 5)
293 # b*=2 will not fire, due to abort
288 # b*=2 will not fire, due to abort
294 self.assertEqual(v['b'], 10)
289 self.assertEqual(v['b'], 10)
295
290
296 def test_result(self):
291 def test_result(self):
297 ip = get_ipython()
292 ip = get_ipython()
298 v = self.client[-1]
293 v = self.client[-1]
299 v.activate()
294 v.activate()
300 data = dict(a=111,b=222)
295 data = dict(a=111,b=222)
301 v.push(data, block=True)
296 v.push(data, block=True)
302
297
303 for name in ('a', 'b'):
298 for name in ('a', 'b'):
304 ip.magic('px ' + name)
299 ip.magic('px ' + name)
305 with capture_output(display=False) as io:
300 with capture_output(display=False) as io:
306 ip.magic('pxresult')
301 ip.magic('pxresult')
307 self.assertIn(str(data[name]), io.stdout)
302 self.assertIn(str(data[name]), io.stdout)
308
303
309 @dec.skipif_not_matplotlib
304 @dec.skipif_not_matplotlib
310 def test_px_pylab(self):
305 def test_px_pylab(self):
311 """%pylab works on engines"""
306 """%pylab works on engines"""
312 ip = get_ipython()
307 ip = get_ipython()
313 v = self.client[-1]
308 v = self.client[-1]
314 v.block = True
309 v.block = True
315 v.activate()
310 v.activate()
316
311
317 with capture_output() as io:
312 with capture_output() as io:
318 ip.magic("px %pylab inline")
313 ip.magic("px %pylab inline")
319
314
320 self.assertIn("Populating the interactive namespace from numpy and matplotlib", io.stdout)
315 self.assertIn("Populating the interactive namespace from numpy and matplotlib", io.stdout)
321
316
322 with capture_output(display=False) as io:
317 with capture_output(display=False) as io:
323 ip.magic("px plot(rand(100))")
318 ip.magic("px plot(rand(100))")
324 self.assertIn('Out[', io.stdout)
319 self.assertIn('Out[', io.stdout)
325 self.assertIn('matplotlib.lines', io.stdout)
320 self.assertIn('matplotlib.lines', io.stdout)
326
321
327 def test_pxconfig(self):
322 def test_pxconfig(self):
328 ip = get_ipython()
323 ip = get_ipython()
329 rc = self.client
324 rc = self.client
330 v = rc.activate(-1, '_tst')
325 v = rc.activate(-1, '_tst')
331 self.assertEqual(v.targets, rc.ids[-1])
326 self.assertEqual(v.targets, rc.ids[-1])
332 ip.magic("%pxconfig_tst -t :")
327 ip.magic("%pxconfig_tst -t :")
333 self.assertEqual(v.targets, rc.ids)
328 self.assertEqual(v.targets, rc.ids)
334 ip.magic("%pxconfig_tst -t ::2")
329 ip.magic("%pxconfig_tst -t ::2")
335 self.assertEqual(v.targets, rc.ids[::2])
330 self.assertEqual(v.targets, rc.ids[::2])
336 ip.magic("%pxconfig_tst -t 1::2")
331 ip.magic("%pxconfig_tst -t 1::2")
337 self.assertEqual(v.targets, rc.ids[1::2])
332 self.assertEqual(v.targets, rc.ids[1::2])
338 ip.magic("%pxconfig_tst -t 1")
333 ip.magic("%pxconfig_tst -t 1")
339 self.assertEqual(v.targets, 1)
334 self.assertEqual(v.targets, 1)
340 ip.magic("%pxconfig_tst --block")
335 ip.magic("%pxconfig_tst --block")
341 self.assertEqual(v.block, True)
336 self.assertEqual(v.block, True)
342 ip.magic("%pxconfig_tst --noblock")
337 ip.magic("%pxconfig_tst --noblock")
343 self.assertEqual(v.block, False)
338 self.assertEqual(v.block, False)
344
339
345 def test_cellpx_targets(self):
340 def test_cellpx_targets(self):
346 """%%px --targets doesn't change defaults"""
341 """%%px --targets doesn't change defaults"""
347 ip = get_ipython()
342 ip = get_ipython()
348 rc = self.client
343 rc = self.client
349 view = rc.activate(rc.ids)
344 view = rc.activate(rc.ids)
350 self.assertEqual(view.targets, rc.ids)
345 self.assertEqual(view.targets, rc.ids)
351 ip.magic('pxconfig --verbose')
346 ip.magic('pxconfig --verbose')
352 for cell in ("pass", "1/0"):
347 for cell in ("pass", "1/0"):
353 with capture_output(display=False) as io:
348 with capture_output(display=False) as io:
354 try:
349 try:
355 ip.run_cell_magic("px", "--targets all", cell)
350 ip.run_cell_magic("px", "--targets all", cell)
356 except pmod.RemoteError:
351 except pmod.RemoteError:
357 pass
352 pass
358 self.assertIn('engine(s): all', io.stdout)
353 self.assertIn('engine(s): all', io.stdout)
359 self.assertEqual(view.targets, rc.ids)
354 self.assertEqual(view.targets, rc.ids)
360
355
361
356
362 def test_cellpx_block(self):
357 def test_cellpx_block(self):
363 """%%px --block doesn't change default"""
358 """%%px --block doesn't change default"""
364 ip = get_ipython()
359 ip = get_ipython()
365 rc = self.client
360 rc = self.client
366 view = rc.activate(rc.ids)
361 view = rc.activate(rc.ids)
367 view.block = False
362 view.block = False
368 self.assertEqual(view.targets, rc.ids)
363 self.assertEqual(view.targets, rc.ids)
369 ip.magic('pxconfig --verbose')
364 ip.magic('pxconfig --verbose')
370 for cell in ("pass", "1/0"):
365 for cell in ("pass", "1/0"):
371 with capture_output(display=False) as io:
366 with capture_output(display=False) as io:
372 try:
367 try:
373 ip.run_cell_magic("px", "--block", cell)
368 ip.run_cell_magic("px", "--block", cell)
374 except pmod.RemoteError:
369 except pmod.RemoteError:
375 pass
370 pass
376 self.assertNotIn('Async', io.stdout)
371 self.assertNotIn('Async', io.stdout)
377 self.assertEqual(view.block, False)
372 self.assertEqual(view.block, False)
378
373
379
374
@@ -1,811 +1,808 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 base64
19 import base64
20 import sys
20 import sys
21 import platform
21 import platform
22 import time
22 import time
23 from collections import namedtuple
23 from collections import namedtuple
24 from tempfile import mktemp
24 from tempfile import mktemp
25 from StringIO import StringIO
26
25
27 import zmq
26 import zmq
28 from nose import SkipTest
29 from nose.plugins.attrib import attr
27 from nose.plugins.attrib import attr
30
28
31 from IPython.testing import decorators as dec
29 from IPython.testing import decorators as dec
32 from IPython.utils.io import capture_output
30 from IPython.utils.io import capture_output
33
31
34 from IPython import parallel as pmod
32 from IPython import parallel as pmod
35 from IPython.parallel import error
33 from IPython.parallel import error
36 from IPython.parallel import AsyncResult, AsyncHubResult, AsyncMapResult
34 from IPython.parallel import AsyncResult, AsyncHubResult, AsyncMapResult
37 from IPython.parallel import DirectView
38 from IPython.parallel.util import interactive
35 from IPython.parallel.util import interactive
39
36
40 from IPython.parallel.tests import add_engines
37 from IPython.parallel.tests import add_engines
41
38
42 from .clienttest import ClusterTestCase, crash, wait, skip_without
39 from .clienttest import ClusterTestCase, crash, wait, skip_without
43
40
44 def setup():
41 def setup():
45 add_engines(3, total=True)
42 add_engines(3, total=True)
46
43
47 point = namedtuple("point", "x y")
44 point = namedtuple("point", "x y")
48
45
49 class TestView(ClusterTestCase):
46 class TestView(ClusterTestCase):
50
47
51 def setUp(self):
48 def setUp(self):
52 # On Win XP, wait for resource cleanup, else parallel test group fails
49 # On Win XP, wait for resource cleanup, else parallel test group fails
53 if platform.system() == "Windows" and platform.win32_ver()[0] == "XP":
50 if platform.system() == "Windows" and platform.win32_ver()[0] == "XP":
54 # 1 sec fails. 1.5 sec seems ok. Using 2 sec for margin of safety
51 # 1 sec fails. 1.5 sec seems ok. Using 2 sec for margin of safety
55 time.sleep(2)
52 time.sleep(2)
56 super(TestView, self).setUp()
53 super(TestView, self).setUp()
57
54
58 @attr('crash')
55 @attr('crash')
59 def test_z_crash_mux(self):
56 def test_z_crash_mux(self):
60 """test graceful handling of engine death (direct)"""
57 """test graceful handling of engine death (direct)"""
61 # self.add_engines(1)
58 # self.add_engines(1)
62 eid = self.client.ids[-1]
59 eid = self.client.ids[-1]
63 ar = self.client[eid].apply_async(crash)
60 ar = self.client[eid].apply_async(crash)
64 self.assertRaisesRemote(error.EngineError, ar.get, 10)
61 self.assertRaisesRemote(error.EngineError, ar.get, 10)
65 eid = ar.engine_id
62 eid = ar.engine_id
66 tic = time.time()
63 tic = time.time()
67 while eid in self.client.ids and time.time()-tic < 5:
64 while eid in self.client.ids and time.time()-tic < 5:
68 time.sleep(.01)
65 time.sleep(.01)
69 self.client.spin()
66 self.client.spin()
70 self.assertFalse(eid in self.client.ids, "Engine should have died")
67 self.assertFalse(eid in self.client.ids, "Engine should have died")
71
68
72 def test_push_pull(self):
69 def test_push_pull(self):
73 """test pushing and pulling"""
70 """test pushing and pulling"""
74 data = dict(a=10, b=1.05, c=range(10), d={'e':(1,2),'f':'hi'})
71 data = dict(a=10, b=1.05, c=range(10), d={'e':(1,2),'f':'hi'})
75 t = self.client.ids[-1]
72 t = self.client.ids[-1]
76 v = self.client[t]
73 v = self.client[t]
77 push = v.push
74 push = v.push
78 pull = v.pull
75 pull = v.pull
79 v.block=True
76 v.block=True
80 nengines = len(self.client)
77 nengines = len(self.client)
81 push({'data':data})
78 push({'data':data})
82 d = pull('data')
79 d = pull('data')
83 self.assertEqual(d, data)
80 self.assertEqual(d, data)
84 self.client[:].push({'data':data})
81 self.client[:].push({'data':data})
85 d = self.client[:].pull('data', block=True)
82 d = self.client[:].pull('data', block=True)
86 self.assertEqual(d, nengines*[data])
83 self.assertEqual(d, nengines*[data])
87 ar = push({'data':data}, block=False)
84 ar = push({'data':data}, block=False)
88 self.assertTrue(isinstance(ar, AsyncResult))
85 self.assertTrue(isinstance(ar, AsyncResult))
89 r = ar.get()
86 r = ar.get()
90 ar = self.client[:].pull('data', block=False)
87 ar = self.client[:].pull('data', block=False)
91 self.assertTrue(isinstance(ar, AsyncResult))
88 self.assertTrue(isinstance(ar, AsyncResult))
92 r = ar.get()
89 r = ar.get()
93 self.assertEqual(r, nengines*[data])
90 self.assertEqual(r, nengines*[data])
94 self.client[:].push(dict(a=10,b=20))
91 self.client[:].push(dict(a=10,b=20))
95 r = self.client[:].pull(('a','b'), block=True)
92 r = self.client[:].pull(('a','b'), block=True)
96 self.assertEqual(r, nengines*[[10,20]])
93 self.assertEqual(r, nengines*[[10,20]])
97
94
98 def test_push_pull_function(self):
95 def test_push_pull_function(self):
99 "test pushing and pulling functions"
96 "test pushing and pulling functions"
100 def testf(x):
97 def testf(x):
101 return 2.0*x
98 return 2.0*x
102
99
103 t = self.client.ids[-1]
100 t = self.client.ids[-1]
104 v = self.client[t]
101 v = self.client[t]
105 v.block=True
102 v.block=True
106 push = v.push
103 push = v.push
107 pull = v.pull
104 pull = v.pull
108 execute = v.execute
105 execute = v.execute
109 push({'testf':testf})
106 push({'testf':testf})
110 r = pull('testf')
107 r = pull('testf')
111 self.assertEqual(r(1.0), testf(1.0))
108 self.assertEqual(r(1.0), testf(1.0))
112 execute('r = testf(10)')
109 execute('r = testf(10)')
113 r = pull('r')
110 r = pull('r')
114 self.assertEqual(r, testf(10))
111 self.assertEqual(r, testf(10))
115 ar = self.client[:].push({'testf':testf}, block=False)
112 ar = self.client[:].push({'testf':testf}, block=False)
116 ar.get()
113 ar.get()
117 ar = self.client[:].pull('testf', block=False)
114 ar = self.client[:].pull('testf', block=False)
118 rlist = ar.get()
115 rlist = ar.get()
119 for r in rlist:
116 for r in rlist:
120 self.assertEqual(r(1.0), testf(1.0))
117 self.assertEqual(r(1.0), testf(1.0))
121 execute("def g(x): return x*x")
118 execute("def g(x): return x*x")
122 r = pull(('testf','g'))
119 r = pull(('testf','g'))
123 self.assertEqual((r[0](10),r[1](10)), (testf(10), 100))
120 self.assertEqual((r[0](10),r[1](10)), (testf(10), 100))
124
121
125 def test_push_function_globals(self):
122 def test_push_function_globals(self):
126 """test that pushed functions have access to globals"""
123 """test that pushed functions have access to globals"""
127 @interactive
124 @interactive
128 def geta():
125 def geta():
129 return a
126 return a
130 # self.add_engines(1)
127 # self.add_engines(1)
131 v = self.client[-1]
128 v = self.client[-1]
132 v.block=True
129 v.block=True
133 v['f'] = geta
130 v['f'] = geta
134 self.assertRaisesRemote(NameError, v.execute, 'b=f()')
131 self.assertRaisesRemote(NameError, v.execute, 'b=f()')
135 v.execute('a=5')
132 v.execute('a=5')
136 v.execute('b=f()')
133 v.execute('b=f()')
137 self.assertEqual(v['b'], 5)
134 self.assertEqual(v['b'], 5)
138
135
139 def test_push_function_defaults(self):
136 def test_push_function_defaults(self):
140 """test that pushed functions preserve default args"""
137 """test that pushed functions preserve default args"""
141 def echo(a=10):
138 def echo(a=10):
142 return a
139 return a
143 v = self.client[-1]
140 v = self.client[-1]
144 v.block=True
141 v.block=True
145 v['f'] = echo
142 v['f'] = echo
146 v.execute('b=f()')
143 v.execute('b=f()')
147 self.assertEqual(v['b'], 10)
144 self.assertEqual(v['b'], 10)
148
145
149 def test_get_result(self):
146 def test_get_result(self):
150 """test getting results from the Hub."""
147 """test getting results from the Hub."""
151 c = pmod.Client(profile='iptest')
148 c = pmod.Client(profile='iptest')
152 # self.add_engines(1)
149 # self.add_engines(1)
153 t = c.ids[-1]
150 t = c.ids[-1]
154 v = c[t]
151 v = c[t]
155 v2 = self.client[t]
152 v2 = self.client[t]
156 ar = v.apply_async(wait, 1)
153 ar = v.apply_async(wait, 1)
157 # give the monitor time to notice the message
154 # give the monitor time to notice the message
158 time.sleep(.25)
155 time.sleep(.25)
159 ahr = v2.get_result(ar.msg_ids[0])
156 ahr = v2.get_result(ar.msg_ids[0])
160 self.assertTrue(isinstance(ahr, AsyncHubResult))
157 self.assertTrue(isinstance(ahr, AsyncHubResult))
161 self.assertEqual(ahr.get(), ar.get())
158 self.assertEqual(ahr.get(), ar.get())
162 ar2 = v2.get_result(ar.msg_ids[0])
159 ar2 = v2.get_result(ar.msg_ids[0])
163 self.assertFalse(isinstance(ar2, AsyncHubResult))
160 self.assertFalse(isinstance(ar2, AsyncHubResult))
164 c.spin()
161 c.spin()
165 c.close()
162 c.close()
166
163
167 def test_run_newline(self):
164 def test_run_newline(self):
168 """test that run appends newline to files"""
165 """test that run appends newline to files"""
169 tmpfile = mktemp()
166 tmpfile = mktemp()
170 with open(tmpfile, 'w') as f:
167 with open(tmpfile, 'w') as f:
171 f.write("""def g():
168 f.write("""def g():
172 return 5
169 return 5
173 """)
170 """)
174 v = self.client[-1]
171 v = self.client[-1]
175 v.run(tmpfile, block=True)
172 v.run(tmpfile, block=True)
176 self.assertEqual(v.apply_sync(lambda f: f(), pmod.Reference('g')), 5)
173 self.assertEqual(v.apply_sync(lambda f: f(), pmod.Reference('g')), 5)
177
174
178 def test_apply_tracked(self):
175 def test_apply_tracked(self):
179 """test tracking for apply"""
176 """test tracking for apply"""
180 # self.add_engines(1)
177 # self.add_engines(1)
181 t = self.client.ids[-1]
178 t = self.client.ids[-1]
182 v = self.client[t]
179 v = self.client[t]
183 v.block=False
180 v.block=False
184 def echo(n=1024*1024, **kwargs):
181 def echo(n=1024*1024, **kwargs):
185 with v.temp_flags(**kwargs):
182 with v.temp_flags(**kwargs):
186 return v.apply(lambda x: x, 'x'*n)
183 return v.apply(lambda x: x, 'x'*n)
187 ar = echo(1, track=False)
184 ar = echo(1, track=False)
188 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
185 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
189 self.assertTrue(ar.sent)
186 self.assertTrue(ar.sent)
190 ar = echo(track=True)
187 ar = echo(track=True)
191 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
188 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
192 self.assertEqual(ar.sent, ar._tracker.done)
189 self.assertEqual(ar.sent, ar._tracker.done)
193 ar._tracker.wait()
190 ar._tracker.wait()
194 self.assertTrue(ar.sent)
191 self.assertTrue(ar.sent)
195
192
196 def test_push_tracked(self):
193 def test_push_tracked(self):
197 t = self.client.ids[-1]
194 t = self.client.ids[-1]
198 ns = dict(x='x'*1024*1024)
195 ns = dict(x='x'*1024*1024)
199 v = self.client[t]
196 v = self.client[t]
200 ar = v.push(ns, block=False, track=False)
197 ar = v.push(ns, block=False, track=False)
201 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
198 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
202 self.assertTrue(ar.sent)
199 self.assertTrue(ar.sent)
203
200
204 ar = v.push(ns, block=False, track=True)
201 ar = v.push(ns, block=False, track=True)
205 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
202 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
206 ar._tracker.wait()
203 ar._tracker.wait()
207 self.assertEqual(ar.sent, ar._tracker.done)
204 self.assertEqual(ar.sent, ar._tracker.done)
208 self.assertTrue(ar.sent)
205 self.assertTrue(ar.sent)
209 ar.get()
206 ar.get()
210
207
211 def test_scatter_tracked(self):
208 def test_scatter_tracked(self):
212 t = self.client.ids
209 t = self.client.ids
213 x='x'*1024*1024
210 x='x'*1024*1024
214 ar = self.client[t].scatter('x', x, block=False, track=False)
211 ar = self.client[t].scatter('x', x, block=False, track=False)
215 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
212 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
216 self.assertTrue(ar.sent)
213 self.assertTrue(ar.sent)
217
214
218 ar = self.client[t].scatter('x', x, block=False, track=True)
215 ar = self.client[t].scatter('x', x, block=False, track=True)
219 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
216 self.assertTrue(isinstance(ar._tracker, zmq.MessageTracker))
220 self.assertEqual(ar.sent, ar._tracker.done)
217 self.assertEqual(ar.sent, ar._tracker.done)
221 ar._tracker.wait()
218 ar._tracker.wait()
222 self.assertTrue(ar.sent)
219 self.assertTrue(ar.sent)
223 ar.get()
220 ar.get()
224
221
225 def test_remote_reference(self):
222 def test_remote_reference(self):
226 v = self.client[-1]
223 v = self.client[-1]
227 v['a'] = 123
224 v['a'] = 123
228 ra = pmod.Reference('a')
225 ra = pmod.Reference('a')
229 b = v.apply_sync(lambda x: x, ra)
226 b = v.apply_sync(lambda x: x, ra)
230 self.assertEqual(b, 123)
227 self.assertEqual(b, 123)
231
228
232
229
233 def test_scatter_gather(self):
230 def test_scatter_gather(self):
234 view = self.client[:]
231 view = self.client[:]
235 seq1 = range(16)
232 seq1 = range(16)
236 view.scatter('a', seq1)
233 view.scatter('a', seq1)
237 seq2 = view.gather('a', block=True)
234 seq2 = view.gather('a', block=True)
238 self.assertEqual(seq2, seq1)
235 self.assertEqual(seq2, seq1)
239 self.assertRaisesRemote(NameError, view.gather, 'asdf', block=True)
236 self.assertRaisesRemote(NameError, view.gather, 'asdf', block=True)
240
237
241 @skip_without('numpy')
238 @skip_without('numpy')
242 def test_scatter_gather_numpy(self):
239 def test_scatter_gather_numpy(self):
243 import numpy
240 import numpy
244 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
241 from numpy.testing.utils import assert_array_equal
245 view = self.client[:]
242 view = self.client[:]
246 a = numpy.arange(64)
243 a = numpy.arange(64)
247 view.scatter('a', a, block=True)
244 view.scatter('a', a, block=True)
248 b = view.gather('a', block=True)
245 b = view.gather('a', block=True)
249 assert_array_equal(b, a)
246 assert_array_equal(b, a)
250
247
251 def test_scatter_gather_lazy(self):
248 def test_scatter_gather_lazy(self):
252 """scatter/gather with targets='all'"""
249 """scatter/gather with targets='all'"""
253 view = self.client.direct_view(targets='all')
250 view = self.client.direct_view(targets='all')
254 x = range(64)
251 x = range(64)
255 view.scatter('x', x)
252 view.scatter('x', x)
256 gathered = view.gather('x', block=True)
253 gathered = view.gather('x', block=True)
257 self.assertEqual(gathered, x)
254 self.assertEqual(gathered, x)
258
255
259
256
260 @dec.known_failure_py3
257 @dec.known_failure_py3
261 @skip_without('numpy')
258 @skip_without('numpy')
262 def test_push_numpy_nocopy(self):
259 def test_push_numpy_nocopy(self):
263 import numpy
260 import numpy
264 view = self.client[:]
261 view = self.client[:]
265 a = numpy.arange(64)
262 a = numpy.arange(64)
266 view['A'] = a
263 view['A'] = a
267 @interactive
264 @interactive
268 def check_writeable(x):
265 def check_writeable(x):
269 return x.flags.writeable
266 return x.flags.writeable
270
267
271 for flag in view.apply_sync(check_writeable, pmod.Reference('A')):
268 for flag in view.apply_sync(check_writeable, pmod.Reference('A')):
272 self.assertFalse(flag, "array is writeable, push shouldn't have pickled it")
269 self.assertFalse(flag, "array is writeable, push shouldn't have pickled it")
273
270
274 view.push(dict(B=a))
271 view.push(dict(B=a))
275 for flag in view.apply_sync(check_writeable, pmod.Reference('B')):
272 for flag in view.apply_sync(check_writeable, pmod.Reference('B')):
276 self.assertFalse(flag, "array is writeable, push shouldn't have pickled it")
273 self.assertFalse(flag, "array is writeable, push shouldn't have pickled it")
277
274
278 @skip_without('numpy')
275 @skip_without('numpy')
279 def test_apply_numpy(self):
276 def test_apply_numpy(self):
280 """view.apply(f, ndarray)"""
277 """view.apply(f, ndarray)"""
281 import numpy
278 import numpy
282 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
279 from numpy.testing.utils import assert_array_equal
283
280
284 A = numpy.random.random((100,100))
281 A = numpy.random.random((100,100))
285 view = self.client[-1]
282 view = self.client[-1]
286 for dt in [ 'int32', 'uint8', 'float32', 'float64' ]:
283 for dt in [ 'int32', 'uint8', 'float32', 'float64' ]:
287 B = A.astype(dt)
284 B = A.astype(dt)
288 C = view.apply_sync(lambda x:x, B)
285 C = view.apply_sync(lambda x:x, B)
289 assert_array_equal(B,C)
286 assert_array_equal(B,C)
290
287
291 @skip_without('numpy')
288 @skip_without('numpy')
292 def test_push_pull_recarray(self):
289 def test_push_pull_recarray(self):
293 """push/pull recarrays"""
290 """push/pull recarrays"""
294 import numpy
291 import numpy
295 from numpy.testing.utils import assert_array_equal
292 from numpy.testing.utils import assert_array_equal
296
293
297 view = self.client[-1]
294 view = self.client[-1]
298
295
299 R = numpy.array([
296 R = numpy.array([
300 (1, 'hi', 0.),
297 (1, 'hi', 0.),
301 (2**30, 'there', 2.5),
298 (2**30, 'there', 2.5),
302 (-99999, 'world', -12345.6789),
299 (-99999, 'world', -12345.6789),
303 ], [('n', int), ('s', '|S10'), ('f', float)])
300 ], [('n', int), ('s', '|S10'), ('f', float)])
304
301
305 view['RR'] = R
302 view['RR'] = R
306 R2 = view['RR']
303 R2 = view['RR']
307
304
308 r_dtype, r_shape = view.apply_sync(interactive(lambda : (RR.dtype, RR.shape)))
305 r_dtype, r_shape = view.apply_sync(interactive(lambda : (RR.dtype, RR.shape)))
309 self.assertEqual(r_dtype, R.dtype)
306 self.assertEqual(r_dtype, R.dtype)
310 self.assertEqual(r_shape, R.shape)
307 self.assertEqual(r_shape, R.shape)
311 self.assertEqual(R2.dtype, R.dtype)
308 self.assertEqual(R2.dtype, R.dtype)
312 self.assertEqual(R2.shape, R.shape)
309 self.assertEqual(R2.shape, R.shape)
313 assert_array_equal(R2, R)
310 assert_array_equal(R2, R)
314
311
315 @skip_without('pandas')
312 @skip_without('pandas')
316 def test_push_pull_timeseries(self):
313 def test_push_pull_timeseries(self):
317 """push/pull pandas.TimeSeries"""
314 """push/pull pandas.TimeSeries"""
318 import pandas
315 import pandas
319
316
320 ts = pandas.TimeSeries(range(10))
317 ts = pandas.TimeSeries(range(10))
321
318
322 view = self.client[-1]
319 view = self.client[-1]
323
320
324 view.push(dict(ts=ts), block=True)
321 view.push(dict(ts=ts), block=True)
325 rts = view['ts']
322 rts = view['ts']
326
323
327 self.assertEqual(type(rts), type(ts))
324 self.assertEqual(type(rts), type(ts))
328 self.assertTrue((ts == rts).all())
325 self.assertTrue((ts == rts).all())
329
326
330 def test_map(self):
327 def test_map(self):
331 view = self.client[:]
328 view = self.client[:]
332 def f(x):
329 def f(x):
333 return x**2
330 return x**2
334 data = range(16)
331 data = range(16)
335 r = view.map_sync(f, data)
332 r = view.map_sync(f, data)
336 self.assertEqual(r, map(f, data))
333 self.assertEqual(r, map(f, data))
337
334
338 def test_map_iterable(self):
335 def test_map_iterable(self):
339 """test map on iterables (direct)"""
336 """test map on iterables (direct)"""
340 view = self.client[:]
337 view = self.client[:]
341 # 101 is prime, so it won't be evenly distributed
338 # 101 is prime, so it won't be evenly distributed
342 arr = range(101)
339 arr = range(101)
343 # ensure it will be an iterator, even in Python 3
340 # ensure it will be an iterator, even in Python 3
344 it = iter(arr)
341 it = iter(arr)
345 r = view.map_sync(lambda x: x, it)
342 r = view.map_sync(lambda x: x, it)
346 self.assertEqual(r, list(arr))
343 self.assertEqual(r, list(arr))
347
344
348 @skip_without('numpy')
345 @skip_without('numpy')
349 def test_map_numpy(self):
346 def test_map_numpy(self):
350 """test map on numpy arrays (direct)"""
347 """test map on numpy arrays (direct)"""
351 import numpy
348 import numpy
352 from numpy.testing.utils import assert_array_equal
349 from numpy.testing.utils import assert_array_equal
353
350
354 view = self.client[:]
351 view = self.client[:]
355 # 101 is prime, so it won't be evenly distributed
352 # 101 is prime, so it won't be evenly distributed
356 arr = numpy.arange(101)
353 arr = numpy.arange(101)
357 r = view.map_sync(lambda x: x, arr)
354 r = view.map_sync(lambda x: x, arr)
358 assert_array_equal(r, arr)
355 assert_array_equal(r, arr)
359
356
360 def test_scatter_gather_nonblocking(self):
357 def test_scatter_gather_nonblocking(self):
361 data = range(16)
358 data = range(16)
362 view = self.client[:]
359 view = self.client[:]
363 view.scatter('a', data, block=False)
360 view.scatter('a', data, block=False)
364 ar = view.gather('a', block=False)
361 ar = view.gather('a', block=False)
365 self.assertEqual(ar.get(), data)
362 self.assertEqual(ar.get(), data)
366
363
367 @skip_without('numpy')
364 @skip_without('numpy')
368 def test_scatter_gather_numpy_nonblocking(self):
365 def test_scatter_gather_numpy_nonblocking(self):
369 import numpy
366 import numpy
370 from numpy.testing.utils import assert_array_equal, assert_array_almost_equal
367 from numpy.testing.utils import assert_array_equal
371 a = numpy.arange(64)
368 a = numpy.arange(64)
372 view = self.client[:]
369 view = self.client[:]
373 ar = view.scatter('a', a, block=False)
370 ar = view.scatter('a', a, block=False)
374 self.assertTrue(isinstance(ar, AsyncResult))
371 self.assertTrue(isinstance(ar, AsyncResult))
375 amr = view.gather('a', block=False)
372 amr = view.gather('a', block=False)
376 self.assertTrue(isinstance(amr, AsyncMapResult))
373 self.assertTrue(isinstance(amr, AsyncMapResult))
377 assert_array_equal(amr.get(), a)
374 assert_array_equal(amr.get(), a)
378
375
379 def test_execute(self):
376 def test_execute(self):
380 view = self.client[:]
377 view = self.client[:]
381 # self.client.debug=True
378 # self.client.debug=True
382 execute = view.execute
379 execute = view.execute
383 ar = execute('c=30', block=False)
380 ar = execute('c=30', block=False)
384 self.assertTrue(isinstance(ar, AsyncResult))
381 self.assertTrue(isinstance(ar, AsyncResult))
385 ar = execute('d=[0,1,2]', block=False)
382 ar = execute('d=[0,1,2]', block=False)
386 self.client.wait(ar, 1)
383 self.client.wait(ar, 1)
387 self.assertEqual(len(ar.get()), len(self.client))
384 self.assertEqual(len(ar.get()), len(self.client))
388 for c in view['c']:
385 for c in view['c']:
389 self.assertEqual(c, 30)
386 self.assertEqual(c, 30)
390
387
391 def test_abort(self):
388 def test_abort(self):
392 view = self.client[-1]
389 view = self.client[-1]
393 ar = view.execute('import time; time.sleep(1)', block=False)
390 ar = view.execute('import time; time.sleep(1)', block=False)
394 ar2 = view.apply_async(lambda : 2)
391 ar2 = view.apply_async(lambda : 2)
395 ar3 = view.apply_async(lambda : 3)
392 ar3 = view.apply_async(lambda : 3)
396 view.abort(ar2)
393 view.abort(ar2)
397 view.abort(ar3.msg_ids)
394 view.abort(ar3.msg_ids)
398 self.assertRaises(error.TaskAborted, ar2.get)
395 self.assertRaises(error.TaskAborted, ar2.get)
399 self.assertRaises(error.TaskAborted, ar3.get)
396 self.assertRaises(error.TaskAborted, ar3.get)
400
397
401 def test_abort_all(self):
398 def test_abort_all(self):
402 """view.abort() aborts all outstanding tasks"""
399 """view.abort() aborts all outstanding tasks"""
403 view = self.client[-1]
400 view = self.client[-1]
404 ars = [ view.apply_async(time.sleep, 0.25) for i in range(10) ]
401 ars = [ view.apply_async(time.sleep, 0.25) for i in range(10) ]
405 view.abort()
402 view.abort()
406 view.wait(timeout=5)
403 view.wait(timeout=5)
407 for ar in ars[5:]:
404 for ar in ars[5:]:
408 self.assertRaises(error.TaskAborted, ar.get)
405 self.assertRaises(error.TaskAborted, ar.get)
409
406
410 def test_temp_flags(self):
407 def test_temp_flags(self):
411 view = self.client[-1]
408 view = self.client[-1]
412 view.block=True
409 view.block=True
413 with view.temp_flags(block=False):
410 with view.temp_flags(block=False):
414 self.assertFalse(view.block)
411 self.assertFalse(view.block)
415 self.assertTrue(view.block)
412 self.assertTrue(view.block)
416
413
417 @dec.known_failure_py3
414 @dec.known_failure_py3
418 def test_importer(self):
415 def test_importer(self):
419 view = self.client[-1]
416 view = self.client[-1]
420 view.clear(block=True)
417 view.clear(block=True)
421 with view.importer:
418 with view.importer:
422 import re
419 import re
423
420
424 @interactive
421 @interactive
425 def findall(pat, s):
422 def findall(pat, s):
426 # this globals() step isn't necessary in real code
423 # this globals() step isn't necessary in real code
427 # only to prevent a closure in the test
424 # only to prevent a closure in the test
428 re = globals()['re']
425 re = globals()['re']
429 return re.findall(pat, s)
426 return re.findall(pat, s)
430
427
431 self.assertEqual(view.apply_sync(findall, '\w+', 'hello world'), 'hello world'.split())
428 self.assertEqual(view.apply_sync(findall, '\w+', 'hello world'), 'hello world'.split())
432
429
433 def test_unicode_execute(self):
430 def test_unicode_execute(self):
434 """test executing unicode strings"""
431 """test executing unicode strings"""
435 v = self.client[-1]
432 v = self.client[-1]
436 v.block=True
433 v.block=True
437 if sys.version_info[0] >= 3:
434 if sys.version_info[0] >= 3:
438 code="a='é'"
435 code="a='é'"
439 else:
436 else:
440 code=u"a=u'é'"
437 code=u"a=u'é'"
441 v.execute(code)
438 v.execute(code)
442 self.assertEqual(v['a'], u'é')
439 self.assertEqual(v['a'], u'é')
443
440
444 def test_unicode_apply_result(self):
441 def test_unicode_apply_result(self):
445 """test unicode apply results"""
442 """test unicode apply results"""
446 v = self.client[-1]
443 v = self.client[-1]
447 r = v.apply_sync(lambda : u'é')
444 r = v.apply_sync(lambda : u'é')
448 self.assertEqual(r, u'é')
445 self.assertEqual(r, u'é')
449
446
450 def test_unicode_apply_arg(self):
447 def test_unicode_apply_arg(self):
451 """test passing unicode arguments to apply"""
448 """test passing unicode arguments to apply"""
452 v = self.client[-1]
449 v = self.client[-1]
453
450
454 @interactive
451 @interactive
455 def check_unicode(a, check):
452 def check_unicode(a, check):
456 assert isinstance(a, unicode), "%r is not unicode"%a
453 assert isinstance(a, unicode), "%r is not unicode"%a
457 assert isinstance(check, bytes), "%r is not bytes"%check
454 assert isinstance(check, bytes), "%r is not bytes"%check
458 assert a.encode('utf8') == check, "%s != %s"%(a,check)
455 assert a.encode('utf8') == check, "%s != %s"%(a,check)
459
456
460 for s in [ u'é', u'ßø®∫',u'asdf' ]:
457 for s in [ u'é', u'ßø®∫',u'asdf' ]:
461 try:
458 try:
462 v.apply_sync(check_unicode, s, s.encode('utf8'))
459 v.apply_sync(check_unicode, s, s.encode('utf8'))
463 except error.RemoteError as e:
460 except error.RemoteError as e:
464 if e.ename == 'AssertionError':
461 if e.ename == 'AssertionError':
465 self.fail(e.evalue)
462 self.fail(e.evalue)
466 else:
463 else:
467 raise e
464 raise e
468
465
469 def test_map_reference(self):
466 def test_map_reference(self):
470 """view.map(<Reference>, *seqs) should work"""
467 """view.map(<Reference>, *seqs) should work"""
471 v = self.client[:]
468 v = self.client[:]
472 v.scatter('n', self.client.ids, flatten=True)
469 v.scatter('n', self.client.ids, flatten=True)
473 v.execute("f = lambda x,y: x*y")
470 v.execute("f = lambda x,y: x*y")
474 rf = pmod.Reference('f')
471 rf = pmod.Reference('f')
475 nlist = list(range(10))
472 nlist = list(range(10))
476 mlist = nlist[::-1]
473 mlist = nlist[::-1]
477 expected = [ m*n for m,n in zip(mlist, nlist) ]
474 expected = [ m*n for m,n in zip(mlist, nlist) ]
478 result = v.map_sync(rf, mlist, nlist)
475 result = v.map_sync(rf, mlist, nlist)
479 self.assertEqual(result, expected)
476 self.assertEqual(result, expected)
480
477
481 def test_apply_reference(self):
478 def test_apply_reference(self):
482 """view.apply(<Reference>, *args) should work"""
479 """view.apply(<Reference>, *args) should work"""
483 v = self.client[:]
480 v = self.client[:]
484 v.scatter('n', self.client.ids, flatten=True)
481 v.scatter('n', self.client.ids, flatten=True)
485 v.execute("f = lambda x: n*x")
482 v.execute("f = lambda x: n*x")
486 rf = pmod.Reference('f')
483 rf = pmod.Reference('f')
487 result = v.apply_sync(rf, 5)
484 result = v.apply_sync(rf, 5)
488 expected = [ 5*id for id in self.client.ids ]
485 expected = [ 5*id for id in self.client.ids ]
489 self.assertEqual(result, expected)
486 self.assertEqual(result, expected)
490
487
491 def test_eval_reference(self):
488 def test_eval_reference(self):
492 v = self.client[self.client.ids[0]]
489 v = self.client[self.client.ids[0]]
493 v['g'] = range(5)
490 v['g'] = range(5)
494 rg = pmod.Reference('g[0]')
491 rg = pmod.Reference('g[0]')
495 echo = lambda x:x
492 echo = lambda x:x
496 self.assertEqual(v.apply_sync(echo, rg), 0)
493 self.assertEqual(v.apply_sync(echo, rg), 0)
497
494
498 def test_reference_nameerror(self):
495 def test_reference_nameerror(self):
499 v = self.client[self.client.ids[0]]
496 v = self.client[self.client.ids[0]]
500 r = pmod.Reference('elvis_has_left')
497 r = pmod.Reference('elvis_has_left')
501 echo = lambda x:x
498 echo = lambda x:x
502 self.assertRaisesRemote(NameError, v.apply_sync, echo, r)
499 self.assertRaisesRemote(NameError, v.apply_sync, echo, r)
503
500
504 def test_single_engine_map(self):
501 def test_single_engine_map(self):
505 e0 = self.client[self.client.ids[0]]
502 e0 = self.client[self.client.ids[0]]
506 r = range(5)
503 r = range(5)
507 check = [ -1*i for i in r ]
504 check = [ -1*i for i in r ]
508 result = e0.map_sync(lambda x: -1*x, r)
505 result = e0.map_sync(lambda x: -1*x, r)
509 self.assertEqual(result, check)
506 self.assertEqual(result, check)
510
507
511 def test_len(self):
508 def test_len(self):
512 """len(view) makes sense"""
509 """len(view) makes sense"""
513 e0 = self.client[self.client.ids[0]]
510 e0 = self.client[self.client.ids[0]]
514 self.assertEqual(len(e0), 1)
511 self.assertEqual(len(e0), 1)
515 v = self.client[:]
512 v = self.client[:]
516 self.assertEqual(len(v), len(self.client.ids))
513 self.assertEqual(len(v), len(self.client.ids))
517 v = self.client.direct_view('all')
514 v = self.client.direct_view('all')
518 self.assertEqual(len(v), len(self.client.ids))
515 self.assertEqual(len(v), len(self.client.ids))
519 v = self.client[:2]
516 v = self.client[:2]
520 self.assertEqual(len(v), 2)
517 self.assertEqual(len(v), 2)
521 v = self.client[:1]
518 v = self.client[:1]
522 self.assertEqual(len(v), 1)
519 self.assertEqual(len(v), 1)
523 v = self.client.load_balanced_view()
520 v = self.client.load_balanced_view()
524 self.assertEqual(len(v), len(self.client.ids))
521 self.assertEqual(len(v), len(self.client.ids))
525
522
526
523
527 # begin execute tests
524 # begin execute tests
528
525
529 def test_execute_reply(self):
526 def test_execute_reply(self):
530 e0 = self.client[self.client.ids[0]]
527 e0 = self.client[self.client.ids[0]]
531 e0.block = True
528 e0.block = True
532 ar = e0.execute("5", silent=False)
529 ar = e0.execute("5", silent=False)
533 er = ar.get()
530 er = ar.get()
534 self.assertEqual(str(er), "<ExecuteReply[%i]: 5>" % er.execution_count)
531 self.assertEqual(str(er), "<ExecuteReply[%i]: 5>" % er.execution_count)
535 self.assertEqual(er.pyout['data']['text/plain'], '5')
532 self.assertEqual(er.pyout['data']['text/plain'], '5')
536
533
537 def test_execute_reply_rich(self):
534 def test_execute_reply_rich(self):
538 e0 = self.client[self.client.ids[0]]
535 e0 = self.client[self.client.ids[0]]
539 e0.block = True
536 e0.block = True
540 e0.execute("from IPython.display import Image, HTML")
537 e0.execute("from IPython.display import Image, HTML")
541 ar = e0.execute("Image(data=b'garbage', format='png', width=10)", silent=False)
538 ar = e0.execute("Image(data=b'garbage', format='png', width=10)", silent=False)
542 er = ar.get()
539 er = ar.get()
543 b64data = base64.encodestring(b'garbage').decode('ascii')
540 b64data = base64.encodestring(b'garbage').decode('ascii')
544 self.assertEqual(er._repr_png_(), (b64data, dict(width=10)))
541 self.assertEqual(er._repr_png_(), (b64data, dict(width=10)))
545 ar = e0.execute("HTML('<b>bold</b>')", silent=False)
542 ar = e0.execute("HTML('<b>bold</b>')", silent=False)
546 er = ar.get()
543 er = ar.get()
547 self.assertEqual(er._repr_html_(), "<b>bold</b>")
544 self.assertEqual(er._repr_html_(), "<b>bold</b>")
548
545
549 def test_execute_reply_stdout(self):
546 def test_execute_reply_stdout(self):
550 e0 = self.client[self.client.ids[0]]
547 e0 = self.client[self.client.ids[0]]
551 e0.block = True
548 e0.block = True
552 ar = e0.execute("print (5)", silent=False)
549 ar = e0.execute("print (5)", silent=False)
553 er = ar.get()
550 er = ar.get()
554 self.assertEqual(er.stdout.strip(), '5')
551 self.assertEqual(er.stdout.strip(), '5')
555
552
556 def test_execute_pyout(self):
553 def test_execute_pyout(self):
557 """execute triggers pyout with silent=False"""
554 """execute triggers pyout with silent=False"""
558 view = self.client[:]
555 view = self.client[:]
559 ar = view.execute("5", silent=False, block=True)
556 ar = view.execute("5", silent=False, block=True)
560
557
561 expected = [{'text/plain' : '5'}] * len(view)
558 expected = [{'text/plain' : '5'}] * len(view)
562 mimes = [ out['data'] for out in ar.pyout ]
559 mimes = [ out['data'] for out in ar.pyout ]
563 self.assertEqual(mimes, expected)
560 self.assertEqual(mimes, expected)
564
561
565 def test_execute_silent(self):
562 def test_execute_silent(self):
566 """execute does not trigger pyout with silent=True"""
563 """execute does not trigger pyout with silent=True"""
567 view = self.client[:]
564 view = self.client[:]
568 ar = view.execute("5", block=True)
565 ar = view.execute("5", block=True)
569 expected = [None] * len(view)
566 expected = [None] * len(view)
570 self.assertEqual(ar.pyout, expected)
567 self.assertEqual(ar.pyout, expected)
571
568
572 def test_execute_magic(self):
569 def test_execute_magic(self):
573 """execute accepts IPython commands"""
570 """execute accepts IPython commands"""
574 view = self.client[:]
571 view = self.client[:]
575 view.execute("a = 5")
572 view.execute("a = 5")
576 ar = view.execute("%whos", block=True)
573 ar = view.execute("%whos", block=True)
577 # this will raise, if that failed
574 # this will raise, if that failed
578 ar.get(5)
575 ar.get(5)
579 for stdout in ar.stdout:
576 for stdout in ar.stdout:
580 lines = stdout.splitlines()
577 lines = stdout.splitlines()
581 self.assertEqual(lines[0].split(), ['Variable', 'Type', 'Data/Info'])
578 self.assertEqual(lines[0].split(), ['Variable', 'Type', 'Data/Info'])
582 found = False
579 found = False
583 for line in lines[2:]:
580 for line in lines[2:]:
584 split = line.split()
581 split = line.split()
585 if split == ['a', 'int', '5']:
582 if split == ['a', 'int', '5']:
586 found = True
583 found = True
587 break
584 break
588 self.assertTrue(found, "whos output wrong: %s" % stdout)
585 self.assertTrue(found, "whos output wrong: %s" % stdout)
589
586
590 def test_execute_displaypub(self):
587 def test_execute_displaypub(self):
591 """execute tracks display_pub output"""
588 """execute tracks display_pub output"""
592 view = self.client[:]
589 view = self.client[:]
593 view.execute("from IPython.core.display import *")
590 view.execute("from IPython.core.display import *")
594 ar = view.execute("[ display(i) for i in range(5) ]", block=True)
591 ar = view.execute("[ display(i) for i in range(5) ]", block=True)
595
592
596 expected = [ {u'text/plain' : unicode(j)} for j in range(5) ]
593 expected = [ {u'text/plain' : unicode(j)} for j in range(5) ]
597 for outputs in ar.outputs:
594 for outputs in ar.outputs:
598 mimes = [ out['data'] for out in outputs ]
595 mimes = [ out['data'] for out in outputs ]
599 self.assertEqual(mimes, expected)
596 self.assertEqual(mimes, expected)
600
597
601 def test_apply_displaypub(self):
598 def test_apply_displaypub(self):
602 """apply tracks display_pub output"""
599 """apply tracks display_pub output"""
603 view = self.client[:]
600 view = self.client[:]
604 view.execute("from IPython.core.display import *")
601 view.execute("from IPython.core.display import *")
605
602
606 @interactive
603 @interactive
607 def publish():
604 def publish():
608 [ display(i) for i in range(5) ]
605 [ display(i) for i in range(5) ]
609
606
610 ar = view.apply_async(publish)
607 ar = view.apply_async(publish)
611 ar.get(5)
608 ar.get(5)
612 expected = [ {u'text/plain' : unicode(j)} for j in range(5) ]
609 expected = [ {u'text/plain' : unicode(j)} for j in range(5) ]
613 for outputs in ar.outputs:
610 for outputs in ar.outputs:
614 mimes = [ out['data'] for out in outputs ]
611 mimes = [ out['data'] for out in outputs ]
615 self.assertEqual(mimes, expected)
612 self.assertEqual(mimes, expected)
616
613
617 def test_execute_raises(self):
614 def test_execute_raises(self):
618 """exceptions in execute requests raise appropriately"""
615 """exceptions in execute requests raise appropriately"""
619 view = self.client[-1]
616 view = self.client[-1]
620 ar = view.execute("1/0")
617 ar = view.execute("1/0")
621 self.assertRaisesRemote(ZeroDivisionError, ar.get, 2)
618 self.assertRaisesRemote(ZeroDivisionError, ar.get, 2)
622
619
623 def test_remoteerror_render_exception(self):
620 def test_remoteerror_render_exception(self):
624 """RemoteErrors get nice tracebacks"""
621 """RemoteErrors get nice tracebacks"""
625 view = self.client[-1]
622 view = self.client[-1]
626 ar = view.execute("1/0")
623 ar = view.execute("1/0")
627 ip = get_ipython()
624 ip = get_ipython()
628 ip.user_ns['ar'] = ar
625 ip.user_ns['ar'] = ar
629 with capture_output() as io:
626 with capture_output() as io:
630 ip.run_cell("ar.get(2)")
627 ip.run_cell("ar.get(2)")
631
628
632 self.assertTrue('ZeroDivisionError' in io.stdout, io.stdout)
629 self.assertTrue('ZeroDivisionError' in io.stdout, io.stdout)
633
630
634 def test_compositeerror_render_exception(self):
631 def test_compositeerror_render_exception(self):
635 """CompositeErrors get nice tracebacks"""
632 """CompositeErrors get nice tracebacks"""
636 view = self.client[:]
633 view = self.client[:]
637 ar = view.execute("1/0")
634 ar = view.execute("1/0")
638 ip = get_ipython()
635 ip = get_ipython()
639 ip.user_ns['ar'] = ar
636 ip.user_ns['ar'] = ar
640
637
641 with capture_output() as io:
638 with capture_output() as io:
642 ip.run_cell("ar.get(2)")
639 ip.run_cell("ar.get(2)")
643
640
644 count = min(error.CompositeError.tb_limit, len(view))
641 count = min(error.CompositeError.tb_limit, len(view))
645
642
646 self.assertEqual(io.stdout.count('ZeroDivisionError'), count * 2, io.stdout)
643 self.assertEqual(io.stdout.count('ZeroDivisionError'), count * 2, io.stdout)
647 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
644 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
648 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
645 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
649
646
650 def test_compositeerror_truncate(self):
647 def test_compositeerror_truncate(self):
651 """Truncate CompositeErrors with many exceptions"""
648 """Truncate CompositeErrors with many exceptions"""
652 view = self.client[:]
649 view = self.client[:]
653 msg_ids = []
650 msg_ids = []
654 for i in range(10):
651 for i in range(10):
655 ar = view.execute("1/0")
652 ar = view.execute("1/0")
656 msg_ids.extend(ar.msg_ids)
653 msg_ids.extend(ar.msg_ids)
657
654
658 ar = self.client.get_result(msg_ids)
655 ar = self.client.get_result(msg_ids)
659 try:
656 try:
660 ar.get()
657 ar.get()
661 except error.CompositeError as _e:
658 except error.CompositeError as _e:
662 e = _e
659 e = _e
663 else:
660 else:
664 self.fail("Should have raised CompositeError")
661 self.fail("Should have raised CompositeError")
665
662
666 lines = e.render_traceback()
663 lines = e.render_traceback()
667 with capture_output() as io:
664 with capture_output() as io:
668 e.print_traceback()
665 e.print_traceback()
669
666
670 self.assertTrue("more exceptions" in lines[-1])
667 self.assertTrue("more exceptions" in lines[-1])
671 count = e.tb_limit
668 count = e.tb_limit
672
669
673 self.assertEqual(io.stdout.count('ZeroDivisionError'), 2 * count, io.stdout)
670 self.assertEqual(io.stdout.count('ZeroDivisionError'), 2 * count, io.stdout)
674 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
671 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
675 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
672 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
676
673
677 @dec.skipif_not_matplotlib
674 @dec.skipif_not_matplotlib
678 def test_magic_pylab(self):
675 def test_magic_pylab(self):
679 """%pylab works on engines"""
676 """%pylab works on engines"""
680 view = self.client[-1]
677 view = self.client[-1]
681 ar = view.execute("%pylab inline")
678 ar = view.execute("%pylab inline")
682 # at least check if this raised:
679 # at least check if this raised:
683 reply = ar.get(5)
680 reply = ar.get(5)
684 # include imports, in case user config
681 # include imports, in case user config
685 ar = view.execute("plot(rand(100))", silent=False)
682 ar = view.execute("plot(rand(100))", silent=False)
686 reply = ar.get(5)
683 reply = ar.get(5)
687 self.assertEqual(len(reply.outputs), 1)
684 self.assertEqual(len(reply.outputs), 1)
688 output = reply.outputs[0]
685 output = reply.outputs[0]
689 self.assertTrue("data" in output)
686 self.assertTrue("data" in output)
690 data = output['data']
687 data = output['data']
691 self.assertTrue("image/png" in data)
688 self.assertTrue("image/png" in data)
692
689
693 def test_func_default_func(self):
690 def test_func_default_func(self):
694 """interactively defined function as apply func default"""
691 """interactively defined function as apply func default"""
695 def foo():
692 def foo():
696 return 'foo'
693 return 'foo'
697
694
698 def bar(f=foo):
695 def bar(f=foo):
699 return f()
696 return f()
700
697
701 view = self.client[-1]
698 view = self.client[-1]
702 ar = view.apply_async(bar)
699 ar = view.apply_async(bar)
703 r = ar.get(10)
700 r = ar.get(10)
704 self.assertEqual(r, 'foo')
701 self.assertEqual(r, 'foo')
705 def test_data_pub_single(self):
702 def test_data_pub_single(self):
706 view = self.client[-1]
703 view = self.client[-1]
707 ar = view.execute('\n'.join([
704 ar = view.execute('\n'.join([
708 'from IPython.kernel.zmq.datapub import publish_data',
705 'from IPython.kernel.zmq.datapub import publish_data',
709 'for i in range(5):',
706 'for i in range(5):',
710 ' publish_data(dict(i=i))'
707 ' publish_data(dict(i=i))'
711 ]), block=False)
708 ]), block=False)
712 self.assertTrue(isinstance(ar.data, dict))
709 self.assertTrue(isinstance(ar.data, dict))
713 ar.get(5)
710 ar.get(5)
714 self.assertEqual(ar.data, dict(i=4))
711 self.assertEqual(ar.data, dict(i=4))
715
712
716 def test_data_pub(self):
713 def test_data_pub(self):
717 view = self.client[:]
714 view = self.client[:]
718 ar = view.execute('\n'.join([
715 ar = view.execute('\n'.join([
719 'from IPython.kernel.zmq.datapub import publish_data',
716 'from IPython.kernel.zmq.datapub import publish_data',
720 'for i in range(5):',
717 'for i in range(5):',
721 ' publish_data(dict(i=i))'
718 ' publish_data(dict(i=i))'
722 ]), block=False)
719 ]), block=False)
723 self.assertTrue(all(isinstance(d, dict) for d in ar.data))
720 self.assertTrue(all(isinstance(d, dict) for d in ar.data))
724 ar.get(5)
721 ar.get(5)
725 self.assertEqual(ar.data, [dict(i=4)] * len(ar))
722 self.assertEqual(ar.data, [dict(i=4)] * len(ar))
726
723
727 def test_can_list_arg(self):
724 def test_can_list_arg(self):
728 """args in lists are canned"""
725 """args in lists are canned"""
729 view = self.client[-1]
726 view = self.client[-1]
730 view['a'] = 128
727 view['a'] = 128
731 rA = pmod.Reference('a')
728 rA = pmod.Reference('a')
732 ar = view.apply_async(lambda x: x, [rA])
729 ar = view.apply_async(lambda x: x, [rA])
733 r = ar.get(5)
730 r = ar.get(5)
734 self.assertEqual(r, [128])
731 self.assertEqual(r, [128])
735
732
736 def test_can_dict_arg(self):
733 def test_can_dict_arg(self):
737 """args in dicts are canned"""
734 """args in dicts are canned"""
738 view = self.client[-1]
735 view = self.client[-1]
739 view['a'] = 128
736 view['a'] = 128
740 rA = pmod.Reference('a')
737 rA = pmod.Reference('a')
741 ar = view.apply_async(lambda x: x, dict(foo=rA))
738 ar = view.apply_async(lambda x: x, dict(foo=rA))
742 r = ar.get(5)
739 r = ar.get(5)
743 self.assertEqual(r, dict(foo=128))
740 self.assertEqual(r, dict(foo=128))
744
741
745 def test_can_list_kwarg(self):
742 def test_can_list_kwarg(self):
746 """kwargs in lists are canned"""
743 """kwargs in lists are canned"""
747 view = self.client[-1]
744 view = self.client[-1]
748 view['a'] = 128
745 view['a'] = 128
749 rA = pmod.Reference('a')
746 rA = pmod.Reference('a')
750 ar = view.apply_async(lambda x=5: x, x=[rA])
747 ar = view.apply_async(lambda x=5: x, x=[rA])
751 r = ar.get(5)
748 r = ar.get(5)
752 self.assertEqual(r, [128])
749 self.assertEqual(r, [128])
753
750
754 def test_can_dict_kwarg(self):
751 def test_can_dict_kwarg(self):
755 """kwargs in dicts are canned"""
752 """kwargs in dicts are canned"""
756 view = self.client[-1]
753 view = self.client[-1]
757 view['a'] = 128
754 view['a'] = 128
758 rA = pmod.Reference('a')
755 rA = pmod.Reference('a')
759 ar = view.apply_async(lambda x=5: x, dict(foo=rA))
756 ar = view.apply_async(lambda x=5: x, dict(foo=rA))
760 r = ar.get(5)
757 r = ar.get(5)
761 self.assertEqual(r, dict(foo=128))
758 self.assertEqual(r, dict(foo=128))
762
759
763 def test_map_ref(self):
760 def test_map_ref(self):
764 """view.map works with references"""
761 """view.map works with references"""
765 view = self.client[:]
762 view = self.client[:]
766 ranks = sorted(self.client.ids)
763 ranks = sorted(self.client.ids)
767 view.scatter('rank', ranks, flatten=True)
764 view.scatter('rank', ranks, flatten=True)
768 rrank = pmod.Reference('rank')
765 rrank = pmod.Reference('rank')
769
766
770 amr = view.map_async(lambda x: x*2, [rrank] * len(view))
767 amr = view.map_async(lambda x: x*2, [rrank] * len(view))
771 drank = amr.get(5)
768 drank = amr.get(5)
772 self.assertEqual(drank, [ r*2 for r in ranks ])
769 self.assertEqual(drank, [ r*2 for r in ranks ])
773
770
774 def test_nested_getitem_setitem(self):
771 def test_nested_getitem_setitem(self):
775 """get and set with view['a.b']"""
772 """get and set with view['a.b']"""
776 view = self.client[-1]
773 view = self.client[-1]
777 view.execute('\n'.join([
774 view.execute('\n'.join([
778 'class A(object): pass',
775 'class A(object): pass',
779 'a = A()',
776 'a = A()',
780 'a.b = 128',
777 'a.b = 128',
781 ]), block=True)
778 ]), block=True)
782 ra = pmod.Reference('a')
779 ra = pmod.Reference('a')
783
780
784 r = view.apply_sync(lambda x: x.b, ra)
781 r = view.apply_sync(lambda x: x.b, ra)
785 self.assertEqual(r, 128)
782 self.assertEqual(r, 128)
786 self.assertEqual(view['a.b'], 128)
783 self.assertEqual(view['a.b'], 128)
787
784
788 view['a.b'] = 0
785 view['a.b'] = 0
789
786
790 r = view.apply_sync(lambda x: x.b, ra)
787 r = view.apply_sync(lambda x: x.b, ra)
791 self.assertEqual(r, 0)
788 self.assertEqual(r, 0)
792 self.assertEqual(view['a.b'], 0)
789 self.assertEqual(view['a.b'], 0)
793
790
794 def test_return_namedtuple(self):
791 def test_return_namedtuple(self):
795 def namedtuplify(x, y):
792 def namedtuplify(x, y):
796 from IPython.parallel.tests.test_view import point
793 from IPython.parallel.tests.test_view import point
797 return point(x, y)
794 return point(x, y)
798
795
799 view = self.client[-1]
796 view = self.client[-1]
800 p = view.apply_sync(namedtuplify, 1, 2)
797 p = view.apply_sync(namedtuplify, 1, 2)
801 self.assertEqual(p.x, 1)
798 self.assertEqual(p.x, 1)
802 self.assertEqual(p.y, 2)
799 self.assertEqual(p.y, 2)
803
800
804 def test_apply_namedtuple(self):
801 def test_apply_namedtuple(self):
805 def echoxy(p):
802 def echoxy(p):
806 return p.y, p.x
803 return p.y, p.x
807
804
808 view = self.client[-1]
805 view = self.client[-1]
809 tup = view.apply_sync(echoxy, point(1, 2))
806 tup = view.apply_sync(echoxy, point(1, 2))
810 self.assertEqual(tup, (2,1))
807 self.assertEqual(tup, (2,1))
811
808
@@ -1,178 +1,177 b''
1 """Experimental code for cleaner support of IPython syntax with unittest.
1 """Experimental code for cleaner support of IPython syntax with unittest.
2
2
3 In IPython up until 0.10, we've used very hacked up nose machinery for running
3 In IPython up until 0.10, we've used very hacked up nose machinery for running
4 tests with IPython special syntax, and this has proved to be extremely slow.
4 tests with IPython special syntax, and this has proved to be extremely slow.
5 This module provides decorators to try a different approach, stemming from a
5 This module provides decorators to try a different approach, stemming from a
6 conversation Brian and I (FP) had about this problem Sept/09.
6 conversation Brian and I (FP) had about this problem Sept/09.
7
7
8 The goal is to be able to easily write simple functions that can be seen by
8 The goal is to be able to easily write simple functions that can be seen by
9 unittest as tests, and ultimately for these to support doctests with full
9 unittest as tests, and ultimately for these to support doctests with full
10 IPython syntax. Nose already offers this based on naming conventions and our
10 IPython syntax. Nose already offers this based on naming conventions and our
11 hackish plugins, but we are seeking to move away from nose dependencies if
11 hackish plugins, but we are seeking to move away from nose dependencies if
12 possible.
12 possible.
13
13
14 This module follows a different approach, based on decorators.
14 This module follows a different approach, based on decorators.
15
15
16 - A decorator called @ipdoctest can mark any function as having a docstring
16 - A decorator called @ipdoctest can mark any function as having a docstring
17 that should be viewed as a doctest, but after syntax conversion.
17 that should be viewed as a doctest, but after syntax conversion.
18
18
19 Authors
19 Authors
20 -------
20 -------
21
21
22 - Fernando Perez <Fernando.Perez@berkeley.edu>
22 - Fernando Perez <Fernando.Perez@berkeley.edu>
23 """
23 """
24
24
25 from __future__ import absolute_import
25 from __future__ import absolute_import
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Copyright (C) 2009-2011 The IPython Development Team
28 # Copyright (C) 2009-2011 The IPython Development Team
29 #
29 #
30 # Distributed under the terms of the BSD License. The full license is in
30 # Distributed under the terms of the BSD License. The full license is in
31 # the file COPYING, distributed as part of this software.
31 # the file COPYING, distributed as part of this software.
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Imports
35 # Imports
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 # Stdlib
38 # Stdlib
39 import re
39 import re
40 import sys
41 import unittest
40 import unittest
42 from doctest import DocTestFinder, DocTestRunner, TestResults
41 from doctest import DocTestFinder, DocTestRunner, TestResults
43
42
44 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
45 # Classes and functions
44 # Classes and functions
46 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
47
46
48 def count_failures(runner):
47 def count_failures(runner):
49 """Count number of failures in a doctest runner.
48 """Count number of failures in a doctest runner.
50
49
51 Code modeled after the summarize() method in doctest.
50 Code modeled after the summarize() method in doctest.
52 """
51 """
53 return [TestResults(f, t) for f, t in runner._name2ft.values() if f > 0 ]
52 return [TestResults(f, t) for f, t in runner._name2ft.values() if f > 0 ]
54
53
55
54
56 class IPython2PythonConverter(object):
55 class IPython2PythonConverter(object):
57 """Convert IPython 'syntax' to valid Python.
56 """Convert IPython 'syntax' to valid Python.
58
57
59 Eventually this code may grow to be the full IPython syntax conversion
58 Eventually this code may grow to be the full IPython syntax conversion
60 implementation, but for now it only does prompt convertion."""
59 implementation, but for now it only does prompt convertion."""
61
60
62 def __init__(self):
61 def __init__(self):
63 self.rps1 = re.compile(r'In\ \[\d+\]: ')
62 self.rps1 = re.compile(r'In\ \[\d+\]: ')
64 self.rps2 = re.compile(r'\ \ \ \.\.\.+: ')
63 self.rps2 = re.compile(r'\ \ \ \.\.\.+: ')
65 self.rout = re.compile(r'Out\[\d+\]: \s*?\n?')
64 self.rout = re.compile(r'Out\[\d+\]: \s*?\n?')
66 self.pyps1 = '>>> '
65 self.pyps1 = '>>> '
67 self.pyps2 = '... '
66 self.pyps2 = '... '
68 self.rpyps1 = re.compile ('(\s*%s)(.*)$' % self.pyps1)
67 self.rpyps1 = re.compile ('(\s*%s)(.*)$' % self.pyps1)
69 self.rpyps2 = re.compile ('(\s*%s)(.*)$' % self.pyps2)
68 self.rpyps2 = re.compile ('(\s*%s)(.*)$' % self.pyps2)
70
69
71 def __call__(self, ds):
70 def __call__(self, ds):
72 """Convert IPython prompts to python ones in a string."""
71 """Convert IPython prompts to python ones in a string."""
73 from . import globalipapp
72 from . import globalipapp
74
73
75 pyps1 = '>>> '
74 pyps1 = '>>> '
76 pyps2 = '... '
75 pyps2 = '... '
77 pyout = ''
76 pyout = ''
78
77
79 dnew = ds
78 dnew = ds
80 dnew = self.rps1.sub(pyps1, dnew)
79 dnew = self.rps1.sub(pyps1, dnew)
81 dnew = self.rps2.sub(pyps2, dnew)
80 dnew = self.rps2.sub(pyps2, dnew)
82 dnew = self.rout.sub(pyout, dnew)
81 dnew = self.rout.sub(pyout, dnew)
83 ip = globalipapp.get_ipython()
82 ip = globalipapp.get_ipython()
84
83
85 # Convert input IPython source into valid Python.
84 # Convert input IPython source into valid Python.
86 out = []
85 out = []
87 newline = out.append
86 newline = out.append
88 for line in dnew.splitlines():
87 for line in dnew.splitlines():
89
88
90 mps1 = self.rpyps1.match(line)
89 mps1 = self.rpyps1.match(line)
91 if mps1 is not None:
90 if mps1 is not None:
92 prompt, text = mps1.groups()
91 prompt, text = mps1.groups()
93 newline(prompt+ip.prefilter(text, False))
92 newline(prompt+ip.prefilter(text, False))
94 continue
93 continue
95
94
96 mps2 = self.rpyps2.match(line)
95 mps2 = self.rpyps2.match(line)
97 if mps2 is not None:
96 if mps2 is not None:
98 prompt, text = mps2.groups()
97 prompt, text = mps2.groups()
99 newline(prompt+ip.prefilter(text, True))
98 newline(prompt+ip.prefilter(text, True))
100 continue
99 continue
101
100
102 newline(line)
101 newline(line)
103 newline('') # ensure a closing newline, needed by doctest
102 newline('') # ensure a closing newline, needed by doctest
104 #print "PYSRC:", '\n'.join(out) # dbg
103 #print "PYSRC:", '\n'.join(out) # dbg
105 return '\n'.join(out)
104 return '\n'.join(out)
106
105
107 #return dnew
106 #return dnew
108
107
109
108
110 class Doc2UnitTester(object):
109 class Doc2UnitTester(object):
111 """Class whose instances act as a decorator for docstring testing.
110 """Class whose instances act as a decorator for docstring testing.
112
111
113 In practice we're only likely to need one instance ever, made below (though
112 In practice we're only likely to need one instance ever, made below (though
114 no attempt is made at turning it into a singleton, there is no need for
113 no attempt is made at turning it into a singleton, there is no need for
115 that).
114 that).
116 """
115 """
117 def __init__(self, verbose=False):
116 def __init__(self, verbose=False):
118 """New decorator.
117 """New decorator.
119
118
120 Parameters
119 Parameters
121 ----------
120 ----------
122
121
123 verbose : boolean, optional (False)
122 verbose : boolean, optional (False)
124 Passed to the doctest finder and runner to control verbosity.
123 Passed to the doctest finder and runner to control verbosity.
125 """
124 """
126 self.verbose = verbose
125 self.verbose = verbose
127 # We can reuse the same finder for all instances
126 # We can reuse the same finder for all instances
128 self.finder = DocTestFinder(verbose=verbose, recurse=False)
127 self.finder = DocTestFinder(verbose=verbose, recurse=False)
129
128
130 def __call__(self, func):
129 def __call__(self, func):
131 """Use as a decorator: doctest a function's docstring as a unittest.
130 """Use as a decorator: doctest a function's docstring as a unittest.
132
131
133 This version runs normal doctests, but the idea is to make it later run
132 This version runs normal doctests, but the idea is to make it later run
134 ipython syntax instead."""
133 ipython syntax instead."""
135
134
136 # Capture the enclosing instance with a different name, so the new
135 # Capture the enclosing instance with a different name, so the new
137 # class below can see it without confusion regarding its own 'self'
136 # class below can see it without confusion regarding its own 'self'
138 # that will point to the test instance at runtime
137 # that will point to the test instance at runtime
139 d2u = self
138 d2u = self
140
139
141 # Rewrite the function's docstring to have python syntax
140 # Rewrite the function's docstring to have python syntax
142 if func.__doc__ is not None:
141 if func.__doc__ is not None:
143 func.__doc__ = ip2py(func.__doc__)
142 func.__doc__ = ip2py(func.__doc__)
144
143
145 # Now, create a tester object that is a real unittest instance, so
144 # Now, create a tester object that is a real unittest instance, so
146 # normal unittest machinery (or Nose, or Trial) can find it.
145 # normal unittest machinery (or Nose, or Trial) can find it.
147 class Tester(unittest.TestCase):
146 class Tester(unittest.TestCase):
148 def test(self):
147 def test(self):
149 # Make a new runner per function to be tested
148 # Make a new runner per function to be tested
150 runner = DocTestRunner(verbose=d2u.verbose)
149 runner = DocTestRunner(verbose=d2u.verbose)
151 map(runner.run, d2u.finder.find(func, func.__name__))
150 map(runner.run, d2u.finder.find(func, func.__name__))
152 failed = count_failures(runner)
151 failed = count_failures(runner)
153 if failed:
152 if failed:
154 # Since we only looked at a single function's docstring,
153 # Since we only looked at a single function's docstring,
155 # failed should contain at most one item. More than that
154 # failed should contain at most one item. More than that
156 # is a case we can't handle and should error out on
155 # is a case we can't handle and should error out on
157 if len(failed) > 1:
156 if len(failed) > 1:
158 err = "Invalid number of test results:" % failed
157 err = "Invalid number of test results:" % failed
159 raise ValueError(err)
158 raise ValueError(err)
160 # Report a normal failure.
159 # Report a normal failure.
161 self.fail('failed doctests: %s' % str(failed[0]))
160 self.fail('failed doctests: %s' % str(failed[0]))
162
161
163 # Rename it so test reports have the original signature.
162 # Rename it so test reports have the original signature.
164 Tester.__name__ = func.__name__
163 Tester.__name__ = func.__name__
165 return Tester
164 return Tester
166
165
167
166
168 def ipdocstring(func):
167 def ipdocstring(func):
169 """Change the function docstring via ip2py.
168 """Change the function docstring via ip2py.
170 """
169 """
171 if func.__doc__ is not None:
170 if func.__doc__ is not None:
172 func.__doc__ = ip2py(func.__doc__)
171 func.__doc__ = ip2py(func.__doc__)
173 return func
172 return func
174
173
175
174
176 # Make an instance of the classes for public use
175 # Make an instance of the classes for public use
177 ipdoctest = Doc2UnitTester()
176 ipdoctest = Doc2UnitTester()
178 ip2py = IPython2PythonConverter()
177 ip2py = IPython2PythonConverter()
General Comments 0
You need to be logged in to leave comments. Login now