Show More
@@ -1,43 +1,45 b'' | |||||
1 | """These kinds of tests are less than ideal, but at least they run. |
|
1 | """These kinds of tests are less than ideal, but at least they run. | |
2 |
|
2 | |||
3 | This was an old test that was being run interactively in the top-level tests/ |
|
3 | This was an old test that was being run interactively in the top-level tests/ | |
4 | directory, which we are removing. For now putting this here ensures at least |
|
4 | directory, which we are removing. For now putting this here ensures at least | |
5 | we do run the test, though ultimately this functionality should all be tested |
|
5 | we do run the test, though ultimately this functionality should all be tested | |
6 | with better-isolated tests that don't rely on the global instance in iptest. |
|
6 | with better-isolated tests that don't rely on the global instance in iptest. | |
7 | """ |
|
7 | """ | |
|
8 | from IPython.utils import py3compat | |||
8 |
|
9 | |||
|
10 | @py3compat.doctest_refactor_print | |||
9 | def doctest_autocall(): |
|
11 | def doctest_autocall(): | |
10 | """ |
|
12 | """ | |
11 | In [1]: def f1(a,b,c): |
|
13 | In [1]: def f1(a,b,c): | |
12 | ...: return a+b+c |
|
14 | ...: return a+b+c | |
13 | ...: |
|
15 | ...: | |
14 |
|
16 | |||
15 | In [2]: def f2(a): |
|
17 | In [2]: def f2(a): | |
16 | ...: return a + a |
|
18 | ...: return a + a | |
17 | ...: |
|
19 | ...: | |
18 |
|
20 | |||
19 | In [3]: ;f2 a b c |
|
21 | In [3]: ;f2 a b c | |
20 | Out[3]: 'a b ca b c' |
|
22 | Out[3]: 'a b ca b c' | |
21 |
|
23 | |||
22 | In [4]: assert _ == "a b ca b c" |
|
24 | In [4]: assert _ == "a b ca b c" | |
23 |
|
25 | |||
24 | In [5]: ,f1 a b c |
|
26 | In [5]: ,f1 a b c | |
25 | Out[5]: 'abc' |
|
27 | Out[5]: 'abc' | |
26 |
|
28 | |||
27 | In [6]: assert _ == 'abc' |
|
29 | In [6]: assert _ == 'abc' | |
28 |
|
30 | |||
29 | In [7]: print _ |
|
31 | In [7]: print _ | |
30 | abc |
|
32 | abc | |
31 |
|
33 | |||
32 | In [8]: /f1 1,2,3 |
|
34 | In [8]: /f1 1,2,3 | |
33 | Out[8]: 6 |
|
35 | Out[8]: 6 | |
34 |
|
36 | |||
35 | In [9]: assert _ == 6 |
|
37 | In [9]: assert _ == 6 | |
36 |
|
38 | |||
37 | In [10]: /f2 4 |
|
39 | In [10]: /f2 4 | |
38 | Out[10]: 8 |
|
40 | Out[10]: 8 | |
39 |
|
41 | |||
40 | In [11]: assert _ == 8 |
|
42 | In [11]: assert _ == 8 | |
41 |
|
43 | |||
42 | In [11]: del f1, f2 |
|
44 | In [11]: del f1, f2 | |
43 | """ |
|
45 | """ |
@@ -1,165 +1,167 b'' | |||||
1 | """Tests for input handlers. |
|
1 | """Tests for input handlers. | |
2 | """ |
|
2 | """ | |
3 | #----------------------------------------------------------------------------- |
|
3 | #----------------------------------------------------------------------------- | |
4 | # Module imports |
|
4 | # Module imports | |
5 | #----------------------------------------------------------------------------- |
|
5 | #----------------------------------------------------------------------------- | |
6 |
|
6 | |||
7 | # third party |
|
7 | # third party | |
8 | import nose.tools as nt |
|
8 | import nose.tools as nt | |
9 |
|
9 | |||
10 | # our own packages |
|
10 | # our own packages | |
11 | from IPython.core import autocall |
|
11 | from IPython.core import autocall | |
12 | from IPython.testing import decorators as dec |
|
12 | from IPython.testing import decorators as dec | |
13 | from IPython.testing import tools as tt |
|
13 | from IPython.testing import tools as tt | |
14 | from IPython.testing.globalipapp import get_ipython |
|
14 | from IPython.testing.globalipapp import get_ipython | |
15 |
|
15 | |||
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 | # Globals |
|
17 | # Globals | |
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 |
|
19 | |||
20 | # Get the public instance of IPython |
|
20 | # Get the public instance of IPython | |
21 | ip = get_ipython() |
|
21 | ip = get_ipython() | |
22 |
|
22 | |||
23 | failures = [] |
|
23 | failures = [] | |
24 | num_tests = 0 |
|
24 | num_tests = 0 | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | # Test functions |
|
27 | # Test functions | |
28 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
29 |
|
29 | |||
30 | class CallableIndexable(object): |
|
30 | class CallableIndexable(object): | |
31 | def __getitem__(self, idx): return True |
|
31 | def __getitem__(self, idx): return True | |
32 | def __call__(self, *args, **kws): return True |
|
32 | def __call__(self, *args, **kws): return True | |
33 |
|
33 | |||
34 |
|
34 | |||
35 | class Autocallable(autocall.IPyAutocall): |
|
35 | class Autocallable(autocall.IPyAutocall): | |
36 | def __call__(self): |
|
36 | def __call__(self): | |
37 | return "called" |
|
37 | return "called" | |
38 |
|
38 | |||
39 |
|
39 | |||
40 | def run(tests): |
|
40 | def run(tests): | |
41 | """Loop through a list of (pre, post) inputs, where pre is the string |
|
41 | """Loop through a list of (pre, post) inputs, where pre is the string | |
42 | handed to ipython, and post is how that string looks after it's been |
|
42 | handed to ipython, and post is how that string looks after it's been | |
43 | transformed (i.e. ipython's notion of _i)""" |
|
43 | transformed (i.e. ipython's notion of _i)""" | |
44 | tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests) |
|
44 | tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests) | |
45 |
|
45 | |||
46 |
|
46 | |||
47 | def test_handlers(): |
|
47 | def test_handlers(): | |
48 | # alias expansion |
|
48 | # alias expansion | |
49 |
|
49 | |||
50 | # We're using 'true' as our syscall of choice because it doesn't |
|
50 | # We're using 'true' as our syscall of choice because it doesn't | |
51 | # write anything to stdout. |
|
51 | # write anything to stdout. | |
52 |
|
52 | |||
53 | # Turn off actual execution of aliases, because it's noisy |
|
53 | # Turn off actual execution of aliases, because it's noisy | |
54 | old_system_cmd = ip.system |
|
54 | old_system_cmd = ip.system | |
55 | ip.system = lambda cmd: None |
|
55 | ip.system = lambda cmd: None | |
56 |
|
56 | |||
57 |
|
57 | |||
58 | ip.alias_manager.alias_table['an_alias'] = (0, 'true') |
|
58 | ip.alias_manager.alias_table['an_alias'] = (0, 'true') | |
59 | # These are useful for checking a particular recursive alias issue |
|
59 | # These are useful for checking a particular recursive alias issue | |
60 | ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top') |
|
60 | ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top') | |
61 | ip.alias_manager.alias_table['d'] = (0, 'true') |
|
61 | ip.alias_manager.alias_table['d'] = (0, 'true') | |
62 | run([("an_alias", 'get_ipython().system(u"true ")'), # alias |
|
62 | run([(i,py3compat.u_format(o)) for i,o in \ | |
|
63 | [("an_alias", 'get_ipython().system({u}"true ")'), # alias | |||
63 | # Below: recursive aliases should expand whitespace-surrounded |
|
64 | # Below: recursive aliases should expand whitespace-surrounded | |
64 | # chars, *not* initial chars which happen to be aliases: |
|
65 | # chars, *not* initial chars which happen to be aliases: | |
65 | ("top", 'get_ipython().system(u"d:/cygwin/top ")'), |
|
66 | ("top", 'get_ipython().system({u}"d:/cygwin/top ")'), | |
66 | ]) |
|
67 | ]]) | |
67 | ip.system = old_system_cmd |
|
68 | ip.system = old_system_cmd | |
68 |
|
69 | |||
69 | call_idx = CallableIndexable() |
|
70 | call_idx = CallableIndexable() | |
70 | ip.user_ns['call_idx'] = call_idx |
|
71 | ip.user_ns['call_idx'] = call_idx | |
71 |
|
72 | |||
72 | # For many of the below, we're also checking that leading whitespace |
|
73 | # For many of the below, we're also checking that leading whitespace | |
73 | # turns off the esc char, which it should unless there is a continuation |
|
74 | # turns off the esc char, which it should unless there is a continuation | |
74 | # line. |
|
75 | # line. | |
75 | run([('"no change"', '"no change"'), # normal |
|
76 | run([(i,py3compat.u_format(o)) for i,o in \ | |
76 | ("!true", 'get_ipython().system(u"true")'), # shell_escapes |
|
77 | [('"no change"', '"no change"'), # normal | |
77 |
("! |
|
78 | ("!true", 'get_ipython().system({u}"true")'), # shell_escapes | |
78 |
("!!true", |
|
79 | ("!! true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic | |
79 |
(" |
|
80 | ("!!true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic | |
80 |
("lsmagic", |
|
81 | ("%lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic | |
|
82 | ("lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic | |||
81 | #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache |
|
83 | #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache | |
82 |
|
84 | |||
83 | # post-esc-char whitespace goes inside |
|
85 | # post-esc-char whitespace goes inside | |
84 | ("! true", 'get_ipython().system(u" true")'), |
|
86 | ("! true", 'get_ipython().system({u}" true")'), | |
85 |
|
87 | |||
86 | # handle_help |
|
88 | # handle_help | |
87 |
|
89 | |||
88 | # These are weak tests -- just looking at what the help handlers |
|
90 | # These are weak tests -- just looking at what the help handlers | |
89 | # logs, which is not how it really does its work. But it still |
|
91 | # logs, which is not how it really does its work. But it still | |
90 | # lets us check the key paths through the handler. |
|
92 | # lets us check the key paths through the handler. | |
91 |
|
93 | |||
92 | ("x=1 # what?", "x=1 # what?"), # no help if valid python |
|
94 | ("x=1 # what?", "x=1 # what?"), # no help if valid python | |
93 | ]) |
|
95 | ]]) | |
94 |
|
96 | |||
95 | # multi_line_specials |
|
97 | # multi_line_specials | |
96 | ip.prefilter_manager.multi_line_specials = False |
|
98 | ip.prefilter_manager.multi_line_specials = False | |
97 | # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion |
|
99 | # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion | |
98 | run([ |
|
100 | run([ | |
99 | ('if 1:\n !true', 'if 1:\n !true'), |
|
101 | ('if 1:\n !true', 'if 1:\n !true'), | |
100 | ('if 1:\n lsmagic', 'if 1:\n lsmagic'), |
|
102 | ('if 1:\n lsmagic', 'if 1:\n lsmagic'), | |
101 | ('if 1:\n an_alias', 'if 1:\n an_alias'), |
|
103 | ('if 1:\n an_alias', 'if 1:\n an_alias'), | |
102 | ]) |
|
104 | ]) | |
103 |
|
105 | |||
104 | ip.prefilter_manager.multi_line_specials = True |
|
106 | ip.prefilter_manager.multi_line_specials = True | |
105 | # initial indents must be preserved. |
|
107 | # initial indents must be preserved. | |
106 | run([ |
|
108 | run([(i,py3compat.u_format(o)) for i,o in \ | |
107 |
|
|
109 | [('if 1:\n !true', 'if 1:\n get_ipython().system({u}"true")'), | |
108 | ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic(u"lsmagic ")'), |
|
110 | ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic({u}"lsmagic ")'), | |
109 | ('if 1:\n an_alias', 'if 1:\n get_ipython().system(u"true ")'), |
|
111 | ('if 1:\n an_alias', 'if 1:\n get_ipython().system({u}"true ")'), | |
110 | # Weird one |
|
112 | # Weird one | |
111 | ('if 1:\n !!true', 'if 1:\n get_ipython().magic(u"sx true")'), |
|
113 | ('if 1:\n !!true', 'if 1:\n get_ipython().magic({u}"sx true")'), | |
112 |
|
114 | |||
113 | # Even with m_l_s on, autocall is off even with special chars |
|
115 | # Even with m_l_s on, autocall is off even with special chars | |
114 | ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'), |
|
116 | ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'), | |
115 | ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'), |
|
117 | ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'), | |
116 | ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'), |
|
118 | ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'), | |
117 | ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'), |
|
119 | ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'), | |
118 | # What about !! |
|
120 | # What about !! | |
119 | ]) |
|
121 | ]]) | |
120 |
|
122 | |||
121 | # Objects which are instances of IPyAutocall are *always* autocalled |
|
123 | # Objects which are instances of IPyAutocall are *always* autocalled | |
122 | autocallable = Autocallable() |
|
124 | autocallable = Autocallable() | |
123 | ip.user_ns['autocallable'] = autocallable |
|
125 | ip.user_ns['autocallable'] = autocallable | |
124 |
|
126 | |||
125 | # auto |
|
127 | # auto | |
126 | ip.magic('autocall 0') |
|
128 | ip.magic('autocall 0') | |
127 | # Only explicit escapes or instances of IPyAutocallable should get |
|
129 | # Only explicit escapes or instances of IPyAutocallable should get | |
128 | # expanded |
|
130 | # expanded | |
129 | run([ |
|
131 | run([ | |
130 | ('len "abc"', 'len "abc"'), |
|
132 | ('len "abc"', 'len "abc"'), | |
131 | ('autocallable', 'autocallable()'), |
|
133 | ('autocallable', 'autocallable()'), | |
132 | (",list 1 2 3", 'list("1", "2", "3")'), |
|
134 | (",list 1 2 3", 'list("1", "2", "3")'), | |
133 | (";list 1 2 3", 'list("1 2 3")'), |
|
135 | (";list 1 2 3", 'list("1 2 3")'), | |
134 | ("/len range(1,4)", 'len(range(1,4))'), |
|
136 | ("/len range(1,4)", 'len(range(1,4))'), | |
135 | ]) |
|
137 | ]) | |
136 | ip.magic('autocall 1') |
|
138 | ip.magic('autocall 1') | |
137 | run([ |
|
139 | run([ | |
138 | (",list 1 2 3", 'list("1", "2", "3")'), |
|
140 | (",list 1 2 3", 'list("1", "2", "3")'), | |
139 | (";list 1 2 3", 'list("1 2 3")'), |
|
141 | (";list 1 2 3", 'list("1 2 3")'), | |
140 | ("/len range(1,4)", 'len(range(1,4))'), |
|
142 | ("/len range(1,4)", 'len(range(1,4))'), | |
141 | ('len "abc"', 'len("abc")'), |
|
143 | ('len "abc"', 'len("abc")'), | |
142 | ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens |
|
144 | ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens | |
143 | # Autocall is turned off if first arg is [] and the object |
|
145 | # Autocall is turned off if first arg is [] and the object | |
144 | # is both callable and indexable. Like so: |
|
146 | # is both callable and indexable. Like so: | |
145 | ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__... |
|
147 | ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__... | |
146 | ('call_idx [1]', 'call_idx [1]'), # call_idx *does*.. |
|
148 | ('call_idx [1]', 'call_idx [1]'), # call_idx *does*.. | |
147 | ('call_idx 1', 'call_idx(1)'), |
|
149 | ('call_idx 1', 'call_idx(1)'), | |
148 | ('len', 'len '), # only at 2 does it auto-call on single args |
|
150 | ('len', 'len '), # only at 2 does it auto-call on single args | |
149 | ]) |
|
151 | ]) | |
150 | ip.magic('autocall 2') |
|
152 | ip.magic('autocall 2') | |
151 | run([ |
|
153 | run([ | |
152 | (",list 1 2 3", 'list("1", "2", "3")'), |
|
154 | (",list 1 2 3", 'list("1", "2", "3")'), | |
153 | (";list 1 2 3", 'list("1 2 3")'), |
|
155 | (";list 1 2 3", 'list("1 2 3")'), | |
154 | ("/len range(1,4)", 'len(range(1,4))'), |
|
156 | ("/len range(1,4)", 'len(range(1,4))'), | |
155 | ('len "abc"', 'len("abc")'), |
|
157 | ('len "abc"', 'len("abc")'), | |
156 | ('len "abc";', 'len("abc");'), |
|
158 | ('len "abc";', 'len("abc");'), | |
157 | ('len [1,2]', 'len([1,2])'), |
|
159 | ('len [1,2]', 'len([1,2])'), | |
158 | ('call_idx [1]', 'call_idx [1]'), |
|
160 | ('call_idx [1]', 'call_idx [1]'), | |
159 | ('call_idx 1', 'call_idx(1)'), |
|
161 | ('call_idx 1', 'call_idx(1)'), | |
160 | # This is what's different: |
|
162 | # This is what's different: | |
161 | ('len', 'len()'), # only at 2 does it auto-call on single args |
|
163 | ('len', 'len()'), # only at 2 does it auto-call on single args | |
162 | ]) |
|
164 | ]) | |
163 | ip.magic('autocall 1') |
|
165 | ip.magic('autocall 1') | |
164 |
|
166 | |||
165 | nt.assert_equals(failures, []) |
|
167 | nt.assert_equals(failures, []) |
@@ -1,690 +1,698 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """Tests for the inputsplitter module. |
|
2 | """Tests for the inputsplitter module. | |
3 |
|
3 | |||
4 | Authors |
|
4 | Authors | |
5 | ------- |
|
5 | ------- | |
6 | * Fernando Perez |
|
6 | * Fernando Perez | |
7 | * Robert Kern |
|
7 | * Robert Kern | |
8 | """ |
|
8 | """ | |
9 | #----------------------------------------------------------------------------- |
|
9 | #----------------------------------------------------------------------------- | |
10 | # Copyright (C) 2010 The IPython Development Team |
|
10 | # Copyright (C) 2010 The IPython Development Team | |
11 | # |
|
11 | # | |
12 | # Distributed under the terms of the BSD License. The full license is in |
|
12 | # Distributed under the terms of the BSD License. The full license is in | |
13 | # the file COPYING, distributed as part of this software. |
|
13 | # the file COPYING, distributed as part of this software. | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 |
|
15 | |||
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 | # Imports |
|
17 | # Imports | |
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 | # stdlib |
|
19 | # stdlib | |
20 | import unittest |
|
20 | import unittest | |
21 | import sys |
|
21 | import sys | |
22 |
|
22 | |||
23 | # Third party |
|
23 | # Third party | |
24 | import nose.tools as nt |
|
24 | import nose.tools as nt | |
25 |
|
25 | |||
26 | # Our own |
|
26 | # Our own | |
27 | from IPython.core import inputsplitter as isp |
|
27 | from IPython.core import inputsplitter as isp | |
28 | from IPython.testing import tools as tt |
|
28 | from IPython.testing import tools as tt | |
|
29 | from IPython.utils import py3compat | |||
29 |
|
30 | |||
30 | #----------------------------------------------------------------------------- |
|
31 | #----------------------------------------------------------------------------- | |
31 | # Semi-complete examples (also used as tests) |
|
32 | # Semi-complete examples (also used as tests) | |
32 | #----------------------------------------------------------------------------- |
|
33 | #----------------------------------------------------------------------------- | |
33 |
|
34 | |||
34 | # Note: at the bottom, there's a slightly more complete version of this that |
|
35 | # Note: at the bottom, there's a slightly more complete version of this that | |
35 | # can be useful during development of code here. |
|
36 | # can be useful during development of code here. | |
36 |
|
37 | |||
37 | def mini_interactive_loop(input_func): |
|
38 | def mini_interactive_loop(input_func): | |
38 | """Minimal example of the logic of an interactive interpreter loop. |
|
39 | """Minimal example of the logic of an interactive interpreter loop. | |
39 |
|
40 | |||
40 | This serves as an example, and it is used by the test system with a fake |
|
41 | This serves as an example, and it is used by the test system with a fake | |
41 | raw_input that simulates interactive input.""" |
|
42 | raw_input that simulates interactive input.""" | |
42 |
|
43 | |||
43 | from IPython.core.inputsplitter import InputSplitter |
|
44 | from IPython.core.inputsplitter import InputSplitter | |
44 |
|
45 | |||
45 | isp = InputSplitter() |
|
46 | isp = InputSplitter() | |
46 | # In practice, this input loop would be wrapped in an outside loop to read |
|
47 | # In practice, this input loop would be wrapped in an outside loop to read | |
47 | # input indefinitely, until some exit/quit command was issued. Here we |
|
48 | # input indefinitely, until some exit/quit command was issued. Here we | |
48 | # only illustrate the basic inner loop. |
|
49 | # only illustrate the basic inner loop. | |
49 | while isp.push_accepts_more(): |
|
50 | while isp.push_accepts_more(): | |
50 | indent = ' '*isp.indent_spaces |
|
51 | indent = ' '*isp.indent_spaces | |
51 | prompt = '>>> ' + indent |
|
52 | prompt = '>>> ' + indent | |
52 | line = indent + input_func(prompt) |
|
53 | line = indent + input_func(prompt) | |
53 | isp.push(line) |
|
54 | isp.push(line) | |
54 |
|
55 | |||
55 | # Here we just return input so we can use it in a test suite, but a real |
|
56 | # Here we just return input so we can use it in a test suite, but a real | |
56 | # interpreter would instead send it for execution somewhere. |
|
57 | # interpreter would instead send it for execution somewhere. | |
57 | src = isp.source_reset() |
|
58 | src = isp.source_reset() | |
58 | #print 'Input source was:\n', src # dbg |
|
59 | #print 'Input source was:\n', src # dbg | |
59 | return src |
|
60 | return src | |
60 |
|
61 | |||
61 | #----------------------------------------------------------------------------- |
|
62 | #----------------------------------------------------------------------------- | |
62 | # Test utilities, just for local use |
|
63 | # Test utilities, just for local use | |
63 | #----------------------------------------------------------------------------- |
|
64 | #----------------------------------------------------------------------------- | |
64 |
|
65 | |||
65 | def assemble(block): |
|
66 | def assemble(block): | |
66 | """Assemble a block into multi-line sub-blocks.""" |
|
67 | """Assemble a block into multi-line sub-blocks.""" | |
67 | return ['\n'.join(sub_block)+'\n' for sub_block in block] |
|
68 | return ['\n'.join(sub_block)+'\n' for sub_block in block] | |
68 |
|
69 | |||
69 |
|
70 | |||
70 | def pseudo_input(lines): |
|
71 | def pseudo_input(lines): | |
71 | """Return a function that acts like raw_input but feeds the input list.""" |
|
72 | """Return a function that acts like raw_input but feeds the input list.""" | |
72 | ilines = iter(lines) |
|
73 | ilines = iter(lines) | |
73 | def raw_in(prompt): |
|
74 | def raw_in(prompt): | |
74 | try: |
|
75 | try: | |
75 | return next(ilines) |
|
76 | return next(ilines) | |
76 | except StopIteration: |
|
77 | except StopIteration: | |
77 | return '' |
|
78 | return '' | |
78 | return raw_in |
|
79 | return raw_in | |
79 |
|
80 | |||
80 | #----------------------------------------------------------------------------- |
|
81 | #----------------------------------------------------------------------------- | |
81 | # Tests |
|
82 | # Tests | |
82 | #----------------------------------------------------------------------------- |
|
83 | #----------------------------------------------------------------------------- | |
83 | def test_spaces(): |
|
84 | def test_spaces(): | |
84 | tests = [('', 0), |
|
85 | tests = [('', 0), | |
85 | (' ', 1), |
|
86 | (' ', 1), | |
86 | ('\n', 0), |
|
87 | ('\n', 0), | |
87 | (' \n', 1), |
|
88 | (' \n', 1), | |
88 | ('x', 0), |
|
89 | ('x', 0), | |
89 | (' x', 1), |
|
90 | (' x', 1), | |
90 | (' x',2), |
|
91 | (' x',2), | |
91 | (' x',4), |
|
92 | (' x',4), | |
92 | # Note: tabs are counted as a single whitespace! |
|
93 | # Note: tabs are counted as a single whitespace! | |
93 | ('\tx', 1), |
|
94 | ('\tx', 1), | |
94 | ('\t x', 2), |
|
95 | ('\t x', 2), | |
95 | ] |
|
96 | ] | |
96 | tt.check_pairs(isp.num_ini_spaces, tests) |
|
97 | tt.check_pairs(isp.num_ini_spaces, tests) | |
97 |
|
98 | |||
98 |
|
99 | |||
99 | def test_remove_comments(): |
|
100 | def test_remove_comments(): | |
100 | tests = [('text', 'text'), |
|
101 | tests = [('text', 'text'), | |
101 | ('text # comment', 'text '), |
|
102 | ('text # comment', 'text '), | |
102 | ('text # comment\n', 'text \n'), |
|
103 | ('text # comment\n', 'text \n'), | |
103 | ('text # comment \n', 'text \n'), |
|
104 | ('text # comment \n', 'text \n'), | |
104 | ('line # c \nline\n','line \nline\n'), |
|
105 | ('line # c \nline\n','line \nline\n'), | |
105 | ('line # c \nline#c2 \nline\nline #c\n\n', |
|
106 | ('line # c \nline#c2 \nline\nline #c\n\n', | |
106 | 'line \nline\nline\nline \n\n'), |
|
107 | 'line \nline\nline\nline \n\n'), | |
107 | ] |
|
108 | ] | |
108 | tt.check_pairs(isp.remove_comments, tests) |
|
109 | tt.check_pairs(isp.remove_comments, tests) | |
109 |
|
110 | |||
110 | def test_has_comment(): |
|
111 | def test_has_comment(): | |
111 | tests = [('text', False), |
|
112 | tests = [('text', False), | |
112 | ('text #comment', True), |
|
113 | ('text #comment', True), | |
113 | ('text #comment\n', True), |
|
114 | ('text #comment\n', True), | |
114 | ('#comment', True), |
|
115 | ('#comment', True), | |
115 | ('#comment\n', True), |
|
116 | ('#comment\n', True), | |
116 | ('a = "#string"', False), |
|
117 | ('a = "#string"', False), | |
117 | ('a = "#string" # comment', True), |
|
118 | ('a = "#string" # comment', True), | |
118 | ('a #comment not "string"', True), |
|
119 | ('a #comment not "string"', True), | |
119 | ] |
|
120 | ] | |
120 | tt.check_pairs(isp.has_comment, tests) |
|
121 | tt.check_pairs(isp.has_comment, tests) | |
121 |
|
122 | |||
122 |
|
123 | |||
123 | def test_get_input_encoding(): |
|
124 | def test_get_input_encoding(): | |
124 | encoding = isp.get_input_encoding() |
|
125 | encoding = isp.get_input_encoding() | |
125 | nt.assert_true(isinstance(encoding, basestring)) |
|
126 | nt.assert_true(isinstance(encoding, basestring)) | |
126 | # simple-minded check that at least encoding a simple string works with the |
|
127 | # simple-minded check that at least encoding a simple string works with the | |
127 | # encoding we got. |
|
128 | # encoding we got. | |
128 | nt.assert_equal(u'test'.encode(encoding), b'test') |
|
129 | nt.assert_equal(u'test'.encode(encoding), b'test') | |
129 |
|
130 | |||
130 |
|
131 | |||
131 | class NoInputEncodingTestCase(unittest.TestCase): |
|
132 | class NoInputEncodingTestCase(unittest.TestCase): | |
132 | def setUp(self): |
|
133 | def setUp(self): | |
133 | self.old_stdin = sys.stdin |
|
134 | self.old_stdin = sys.stdin | |
134 | class X: pass |
|
135 | class X: pass | |
135 | fake_stdin = X() |
|
136 | fake_stdin = X() | |
136 | sys.stdin = fake_stdin |
|
137 | sys.stdin = fake_stdin | |
137 |
|
138 | |||
138 | def test(self): |
|
139 | def test(self): | |
139 | # Verify that if sys.stdin has no 'encoding' attribute we do the right |
|
140 | # Verify that if sys.stdin has no 'encoding' attribute we do the right | |
140 | # thing |
|
141 | # thing | |
141 | enc = isp.get_input_encoding() |
|
142 | enc = isp.get_input_encoding() | |
142 | self.assertEqual(enc, 'ascii') |
|
143 | self.assertEqual(enc, 'ascii') | |
143 |
|
144 | |||
144 | def tearDown(self): |
|
145 | def tearDown(self): | |
145 | sys.stdin = self.old_stdin |
|
146 | sys.stdin = self.old_stdin | |
146 |
|
147 | |||
147 |
|
148 | |||
148 | class InputSplitterTestCase(unittest.TestCase): |
|
149 | class InputSplitterTestCase(unittest.TestCase): | |
149 | def setUp(self): |
|
150 | def setUp(self): | |
150 | self.isp = isp.InputSplitter() |
|
151 | self.isp = isp.InputSplitter() | |
151 |
|
152 | |||
152 | def test_reset(self): |
|
153 | def test_reset(self): | |
153 | isp = self.isp |
|
154 | isp = self.isp | |
154 | isp.push('x=1') |
|
155 | isp.push('x=1') | |
155 | isp.reset() |
|
156 | isp.reset() | |
156 | self.assertEqual(isp._buffer, []) |
|
157 | self.assertEqual(isp._buffer, []) | |
157 | self.assertEqual(isp.indent_spaces, 0) |
|
158 | self.assertEqual(isp.indent_spaces, 0) | |
158 | self.assertEqual(isp.source, '') |
|
159 | self.assertEqual(isp.source, '') | |
159 | self.assertEqual(isp.code, None) |
|
160 | self.assertEqual(isp.code, None) | |
160 | self.assertEqual(isp._is_complete, False) |
|
161 | self.assertEqual(isp._is_complete, False) | |
161 |
|
162 | |||
162 | def test_source(self): |
|
163 | def test_source(self): | |
163 | self.isp._store('1') |
|
164 | self.isp._store('1') | |
164 | self.isp._store('2') |
|
165 | self.isp._store('2') | |
165 | self.assertEqual(self.isp.source, '1\n2\n') |
|
166 | self.assertEqual(self.isp.source, '1\n2\n') | |
166 | self.assertTrue(len(self.isp._buffer)>0) |
|
167 | self.assertTrue(len(self.isp._buffer)>0) | |
167 | self.assertEqual(self.isp.source_reset(), '1\n2\n') |
|
168 | self.assertEqual(self.isp.source_reset(), '1\n2\n') | |
168 | self.assertEqual(self.isp._buffer, []) |
|
169 | self.assertEqual(self.isp._buffer, []) | |
169 | self.assertEqual(self.isp.source, '') |
|
170 | self.assertEqual(self.isp.source, '') | |
170 |
|
171 | |||
171 | def test_indent(self): |
|
172 | def test_indent(self): | |
172 | isp = self.isp # shorthand |
|
173 | isp = self.isp # shorthand | |
173 | isp.push('x=1') |
|
174 | isp.push('x=1') | |
174 | self.assertEqual(isp.indent_spaces, 0) |
|
175 | self.assertEqual(isp.indent_spaces, 0) | |
175 | isp.push('if 1:\n x=1') |
|
176 | isp.push('if 1:\n x=1') | |
176 | self.assertEqual(isp.indent_spaces, 4) |
|
177 | self.assertEqual(isp.indent_spaces, 4) | |
177 | isp.push('y=2\n') |
|
178 | isp.push('y=2\n') | |
178 | self.assertEqual(isp.indent_spaces, 0) |
|
179 | self.assertEqual(isp.indent_spaces, 0) | |
179 |
|
180 | |||
180 | def test_indent2(self): |
|
181 | def test_indent2(self): | |
181 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
182 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
182 | if self.isp.input_mode == 'cell': return |
|
183 | if self.isp.input_mode == 'cell': return | |
183 |
|
184 | |||
184 | isp = self.isp |
|
185 | isp = self.isp | |
185 | isp.push('if 1:') |
|
186 | isp.push('if 1:') | |
186 | self.assertEqual(isp.indent_spaces, 4) |
|
187 | self.assertEqual(isp.indent_spaces, 4) | |
187 | isp.push(' x=1') |
|
188 | isp.push(' x=1') | |
188 | self.assertEqual(isp.indent_spaces, 4) |
|
189 | self.assertEqual(isp.indent_spaces, 4) | |
189 | # Blank lines shouldn't change the indent level |
|
190 | # Blank lines shouldn't change the indent level | |
190 | isp.push(' '*2) |
|
191 | isp.push(' '*2) | |
191 | self.assertEqual(isp.indent_spaces, 4) |
|
192 | self.assertEqual(isp.indent_spaces, 4) | |
192 |
|
193 | |||
193 | def test_indent3(self): |
|
194 | def test_indent3(self): | |
194 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
195 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
195 | if self.isp.input_mode == 'cell': return |
|
196 | if self.isp.input_mode == 'cell': return | |
196 |
|
197 | |||
197 | isp = self.isp |
|
198 | isp = self.isp | |
198 | # When a multiline statement contains parens or multiline strings, we |
|
199 | # When a multiline statement contains parens or multiline strings, we | |
199 | # shouldn't get confused. |
|
200 | # shouldn't get confused. | |
200 | isp.push("if 1:") |
|
201 | isp.push("if 1:") | |
201 | isp.push(" x = (1+\n 2)") |
|
202 | isp.push(" x = (1+\n 2)") | |
202 | self.assertEqual(isp.indent_spaces, 4) |
|
203 | self.assertEqual(isp.indent_spaces, 4) | |
203 |
|
204 | |||
204 | def test_indent4(self): |
|
205 | def test_indent4(self): | |
205 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
206 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
206 | if self.isp.input_mode == 'cell': return |
|
207 | if self.isp.input_mode == 'cell': return | |
207 |
|
208 | |||
208 | isp = self.isp |
|
209 | isp = self.isp | |
209 | # whitespace after ':' should not screw up indent level |
|
210 | # whitespace after ':' should not screw up indent level | |
210 | isp.push('if 1: \n x=1') |
|
211 | isp.push('if 1: \n x=1') | |
211 | self.assertEqual(isp.indent_spaces, 4) |
|
212 | self.assertEqual(isp.indent_spaces, 4) | |
212 | isp.push('y=2\n') |
|
213 | isp.push('y=2\n') | |
213 | self.assertEqual(isp.indent_spaces, 0) |
|
214 | self.assertEqual(isp.indent_spaces, 0) | |
214 | isp.push('if 1:\t\n x=1') |
|
215 | isp.push('if 1:\t\n x=1') | |
215 | self.assertEqual(isp.indent_spaces, 4) |
|
216 | self.assertEqual(isp.indent_spaces, 4) | |
216 | isp.push('y=2\n') |
|
217 | isp.push('y=2\n') | |
217 | self.assertEqual(isp.indent_spaces, 0) |
|
218 | self.assertEqual(isp.indent_spaces, 0) | |
218 |
|
219 | |||
219 | def test_dedent_pass(self): |
|
220 | def test_dedent_pass(self): | |
220 | isp = self.isp # shorthand |
|
221 | isp = self.isp # shorthand | |
221 | # should NOT cause dedent |
|
222 | # should NOT cause dedent | |
222 | isp.push('if 1:\n passes = 5') |
|
223 | isp.push('if 1:\n passes = 5') | |
223 | self.assertEqual(isp.indent_spaces, 4) |
|
224 | self.assertEqual(isp.indent_spaces, 4) | |
224 | isp.push('if 1:\n pass') |
|
225 | isp.push('if 1:\n pass') | |
225 | self.assertEqual(isp.indent_spaces, 0) |
|
226 | self.assertEqual(isp.indent_spaces, 0) | |
226 | isp.push('if 1:\n pass ') |
|
227 | isp.push('if 1:\n pass ') | |
227 | self.assertEqual(isp.indent_spaces, 0) |
|
228 | self.assertEqual(isp.indent_spaces, 0) | |
228 |
|
229 | |||
229 | def test_dedent_raise(self): |
|
230 | def test_dedent_raise(self): | |
230 | isp = self.isp # shorthand |
|
231 | isp = self.isp # shorthand | |
231 | # should NOT cause dedent |
|
232 | # should NOT cause dedent | |
232 | isp.push('if 1:\n raised = 4') |
|
233 | isp.push('if 1:\n raised = 4') | |
233 | self.assertEqual(isp.indent_spaces, 4) |
|
234 | self.assertEqual(isp.indent_spaces, 4) | |
234 | isp.push('if 1:\n raise TypeError()') |
|
235 | isp.push('if 1:\n raise TypeError()') | |
235 | self.assertEqual(isp.indent_spaces, 0) |
|
236 | self.assertEqual(isp.indent_spaces, 0) | |
236 | isp.push('if 1:\n raise') |
|
237 | isp.push('if 1:\n raise') | |
237 | self.assertEqual(isp.indent_spaces, 0) |
|
238 | self.assertEqual(isp.indent_spaces, 0) | |
238 | isp.push('if 1:\n raise ') |
|
239 | isp.push('if 1:\n raise ') | |
239 | self.assertEqual(isp.indent_spaces, 0) |
|
240 | self.assertEqual(isp.indent_spaces, 0) | |
240 |
|
241 | |||
241 | def test_dedent_return(self): |
|
242 | def test_dedent_return(self): | |
242 | isp = self.isp # shorthand |
|
243 | isp = self.isp # shorthand | |
243 | # should NOT cause dedent |
|
244 | # should NOT cause dedent | |
244 | isp.push('if 1:\n returning = 4') |
|
245 | isp.push('if 1:\n returning = 4') | |
245 | self.assertEqual(isp.indent_spaces, 4) |
|
246 | self.assertEqual(isp.indent_spaces, 4) | |
246 | isp.push('if 1:\n return 5 + 493') |
|
247 | isp.push('if 1:\n return 5 + 493') | |
247 | self.assertEqual(isp.indent_spaces, 0) |
|
248 | self.assertEqual(isp.indent_spaces, 0) | |
248 | isp.push('if 1:\n return') |
|
249 | isp.push('if 1:\n return') | |
249 | self.assertEqual(isp.indent_spaces, 0) |
|
250 | self.assertEqual(isp.indent_spaces, 0) | |
250 | isp.push('if 1:\n return ') |
|
251 | isp.push('if 1:\n return ') | |
251 | self.assertEqual(isp.indent_spaces, 0) |
|
252 | self.assertEqual(isp.indent_spaces, 0) | |
252 | isp.push('if 1:\n return(0)') |
|
253 | isp.push('if 1:\n return(0)') | |
253 | self.assertEqual(isp.indent_spaces, 0) |
|
254 | self.assertEqual(isp.indent_spaces, 0) | |
254 |
|
255 | |||
255 | def test_push(self): |
|
256 | def test_push(self): | |
256 | isp = self.isp |
|
257 | isp = self.isp | |
257 | self.assertTrue(isp.push('x=1')) |
|
258 | self.assertTrue(isp.push('x=1')) | |
258 |
|
259 | |||
259 | def test_push2(self): |
|
260 | def test_push2(self): | |
260 | isp = self.isp |
|
261 | isp = self.isp | |
261 | self.assertFalse(isp.push('if 1:')) |
|
262 | self.assertFalse(isp.push('if 1:')) | |
262 | for line in [' x=1', '# a comment', ' y=2']: |
|
263 | for line in [' x=1', '# a comment', ' y=2']: | |
263 | self.assertTrue(isp.push(line)) |
|
264 | self.assertTrue(isp.push(line)) | |
264 |
|
265 | |||
265 | def test_push3(self): |
|
266 | def test_push3(self): | |
266 | isp = self.isp |
|
267 | isp = self.isp | |
267 | isp.push('if True:') |
|
268 | isp.push('if True:') | |
268 | isp.push(' a = 1') |
|
269 | isp.push(' a = 1') | |
269 | self.assertFalse(isp.push('b = [1,')) |
|
270 | self.assertFalse(isp.push('b = [1,')) | |
270 |
|
271 | |||
271 | def test_replace_mode(self): |
|
272 | def test_replace_mode(self): | |
272 | isp = self.isp |
|
273 | isp = self.isp | |
273 | isp.input_mode = 'cell' |
|
274 | isp.input_mode = 'cell' | |
274 | isp.push('x=1') |
|
275 | isp.push('x=1') | |
275 | self.assertEqual(isp.source, 'x=1\n') |
|
276 | self.assertEqual(isp.source, 'x=1\n') | |
276 | isp.push('x=2') |
|
277 | isp.push('x=2') | |
277 | self.assertEqual(isp.source, 'x=2\n') |
|
278 | self.assertEqual(isp.source, 'x=2\n') | |
278 |
|
279 | |||
279 | def test_push_accepts_more(self): |
|
280 | def test_push_accepts_more(self): | |
280 | isp = self.isp |
|
281 | isp = self.isp | |
281 | isp.push('x=1') |
|
282 | isp.push('x=1') | |
282 | self.assertFalse(isp.push_accepts_more()) |
|
283 | self.assertFalse(isp.push_accepts_more()) | |
283 |
|
284 | |||
284 | def test_push_accepts_more2(self): |
|
285 | def test_push_accepts_more2(self): | |
285 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
286 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
286 | if self.isp.input_mode == 'cell': return |
|
287 | if self.isp.input_mode == 'cell': return | |
287 |
|
288 | |||
288 | isp = self.isp |
|
289 | isp = self.isp | |
289 | isp.push('if 1:') |
|
290 | isp.push('if 1:') | |
290 | self.assertTrue(isp.push_accepts_more()) |
|
291 | self.assertTrue(isp.push_accepts_more()) | |
291 | isp.push(' x=1') |
|
292 | isp.push(' x=1') | |
292 | self.assertTrue(isp.push_accepts_more()) |
|
293 | self.assertTrue(isp.push_accepts_more()) | |
293 | isp.push('') |
|
294 | isp.push('') | |
294 | self.assertFalse(isp.push_accepts_more()) |
|
295 | self.assertFalse(isp.push_accepts_more()) | |
295 |
|
296 | |||
296 | def test_push_accepts_more3(self): |
|
297 | def test_push_accepts_more3(self): | |
297 | isp = self.isp |
|
298 | isp = self.isp | |
298 | isp.push("x = (2+\n3)") |
|
299 | isp.push("x = (2+\n3)") | |
299 | self.assertFalse(isp.push_accepts_more()) |
|
300 | self.assertFalse(isp.push_accepts_more()) | |
300 |
|
301 | |||
301 | def test_push_accepts_more4(self): |
|
302 | def test_push_accepts_more4(self): | |
302 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
303 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
303 | if self.isp.input_mode == 'cell': return |
|
304 | if self.isp.input_mode == 'cell': return | |
304 |
|
305 | |||
305 | isp = self.isp |
|
306 | isp = self.isp | |
306 | # When a multiline statement contains parens or multiline strings, we |
|
307 | # When a multiline statement contains parens or multiline strings, we | |
307 | # shouldn't get confused. |
|
308 | # shouldn't get confused. | |
308 | # FIXME: we should be able to better handle de-dents in statements like |
|
309 | # FIXME: we should be able to better handle de-dents in statements like | |
309 | # multiline strings and multiline expressions (continued with \ or |
|
310 | # multiline strings and multiline expressions (continued with \ or | |
310 | # parens). Right now we aren't handling the indentation tracking quite |
|
311 | # parens). Right now we aren't handling the indentation tracking quite | |
311 | # correctly with this, though in practice it may not be too much of a |
|
312 | # correctly with this, though in practice it may not be too much of a | |
312 | # problem. We'll need to see. |
|
313 | # problem. We'll need to see. | |
313 | isp.push("if 1:") |
|
314 | isp.push("if 1:") | |
314 | isp.push(" x = (2+") |
|
315 | isp.push(" x = (2+") | |
315 | isp.push(" 3)") |
|
316 | isp.push(" 3)") | |
316 | self.assertTrue(isp.push_accepts_more()) |
|
317 | self.assertTrue(isp.push_accepts_more()) | |
317 | isp.push(" y = 3") |
|
318 | isp.push(" y = 3") | |
318 | self.assertTrue(isp.push_accepts_more()) |
|
319 | self.assertTrue(isp.push_accepts_more()) | |
319 | isp.push('') |
|
320 | isp.push('') | |
320 | self.assertFalse(isp.push_accepts_more()) |
|
321 | self.assertFalse(isp.push_accepts_more()) | |
321 |
|
322 | |||
322 | def test_push_accepts_more5(self): |
|
323 | def test_push_accepts_more5(self): | |
323 | # In cell mode, inputs must be fed in whole blocks, so skip this test |
|
324 | # In cell mode, inputs must be fed in whole blocks, so skip this test | |
324 | if self.isp.input_mode == 'cell': return |
|
325 | if self.isp.input_mode == 'cell': return | |
325 |
|
326 | |||
326 | isp = self.isp |
|
327 | isp = self.isp | |
327 | isp.push('try:') |
|
328 | isp.push('try:') | |
328 | isp.push(' a = 5') |
|
329 | isp.push(' a = 5') | |
329 | isp.push('except:') |
|
330 | isp.push('except:') | |
330 | isp.push(' raise') |
|
331 | isp.push(' raise') | |
331 | self.assertTrue(isp.push_accepts_more()) |
|
332 | self.assertTrue(isp.push_accepts_more()) | |
332 |
|
333 | |||
333 | def test_continuation(self): |
|
334 | def test_continuation(self): | |
334 | isp = self.isp |
|
335 | isp = self.isp | |
335 | isp.push("import os, \\") |
|
336 | isp.push("import os, \\") | |
336 | self.assertTrue(isp.push_accepts_more()) |
|
337 | self.assertTrue(isp.push_accepts_more()) | |
337 | isp.push("sys") |
|
338 | isp.push("sys") | |
338 | self.assertFalse(isp.push_accepts_more()) |
|
339 | self.assertFalse(isp.push_accepts_more()) | |
339 |
|
340 | |||
340 | def test_syntax_error(self): |
|
341 | def test_syntax_error(self): | |
341 | isp = self.isp |
|
342 | isp = self.isp | |
342 | # Syntax errors immediately produce a 'ready' block, so the invalid |
|
343 | # Syntax errors immediately produce a 'ready' block, so the invalid | |
343 | # Python can be sent to the kernel for evaluation with possible ipython |
|
344 | # Python can be sent to the kernel for evaluation with possible ipython | |
344 | # special-syntax conversion. |
|
345 | # special-syntax conversion. | |
345 | isp.push('run foo') |
|
346 | isp.push('run foo') | |
346 | self.assertFalse(isp.push_accepts_more()) |
|
347 | self.assertFalse(isp.push_accepts_more()) | |
347 |
|
348 | |||
348 | def test_unicode(self): |
|
349 | def test_unicode(self): | |
349 | self.isp.push(u"PΓ©rez") |
|
350 | self.isp.push(u"PΓ©rez") | |
350 | self.isp.push(u'\xc3\xa9') |
|
351 | self.isp.push(u'\xc3\xa9') | |
351 | self.isp.push(u"u'\xc3\xa9'") |
|
352 | self.isp.push(u"u'\xc3\xa9'") | |
352 |
|
353 | |||
353 | class InteractiveLoopTestCase(unittest.TestCase): |
|
354 | class InteractiveLoopTestCase(unittest.TestCase): | |
354 | """Tests for an interactive loop like a python shell. |
|
355 | """Tests for an interactive loop like a python shell. | |
355 | """ |
|
356 | """ | |
356 | def check_ns(self, lines, ns): |
|
357 | def check_ns(self, lines, ns): | |
357 | """Validate that the given input lines produce the resulting namespace. |
|
358 | """Validate that the given input lines produce the resulting namespace. | |
358 |
|
359 | |||
359 | Note: the input lines are given exactly as they would be typed in an |
|
360 | Note: the input lines are given exactly as they would be typed in an | |
360 | auto-indenting environment, as mini_interactive_loop above already does |
|
361 | auto-indenting environment, as mini_interactive_loop above already does | |
361 | auto-indenting and prepends spaces to the input. |
|
362 | auto-indenting and prepends spaces to the input. | |
362 | """ |
|
363 | """ | |
363 | src = mini_interactive_loop(pseudo_input(lines)) |
|
364 | src = mini_interactive_loop(pseudo_input(lines)) | |
364 | test_ns = {} |
|
365 | test_ns = {} | |
365 | exec src in test_ns |
|
366 | exec src in test_ns | |
366 | # We can't check that the provided ns is identical to the test_ns, |
|
367 | # We can't check that the provided ns is identical to the test_ns, | |
367 | # because Python fills test_ns with extra keys (copyright, etc). But |
|
368 | # because Python fills test_ns with extra keys (copyright, etc). But | |
368 | # we can check that the given dict is *contained* in test_ns |
|
369 | # we can check that the given dict is *contained* in test_ns | |
369 | for k,v in ns.iteritems(): |
|
370 | for k,v in ns.iteritems(): | |
370 | self.assertEqual(test_ns[k], v) |
|
371 | self.assertEqual(test_ns[k], v) | |
371 |
|
372 | |||
372 | def test_simple(self): |
|
373 | def test_simple(self): | |
373 | self.check_ns(['x=1'], dict(x=1)) |
|
374 | self.check_ns(['x=1'], dict(x=1)) | |
374 |
|
375 | |||
375 | def test_simple2(self): |
|
376 | def test_simple2(self): | |
376 | self.check_ns(['if 1:', 'x=2'], dict(x=2)) |
|
377 | self.check_ns(['if 1:', 'x=2'], dict(x=2)) | |
377 |
|
378 | |||
378 | def test_xy(self): |
|
379 | def test_xy(self): | |
379 | self.check_ns(['x=1; y=2'], dict(x=1, y=2)) |
|
380 | self.check_ns(['x=1; y=2'], dict(x=1, y=2)) | |
380 |
|
381 | |||
381 | def test_abc(self): |
|
382 | def test_abc(self): | |
382 | self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3)) |
|
383 | self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3)) | |
383 |
|
384 | |||
384 | def test_multi(self): |
|
385 | def test_multi(self): | |
385 | self.check_ns(['x =(1+','1+','2)'], dict(x=4)) |
|
386 | self.check_ns(['x =(1+','1+','2)'], dict(x=4)) | |
386 |
|
387 | |||
387 |
|
388 | |||
388 | def test_LineInfo(): |
|
389 | def test_LineInfo(): | |
389 | """Simple test for LineInfo construction and str()""" |
|
390 | """Simple test for LineInfo construction and str()""" | |
390 | linfo = isp.LineInfo(' %cd /home') |
|
391 | linfo = isp.LineInfo(' %cd /home') | |
391 | nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]') |
|
392 | nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]') | |
392 |
|
393 | |||
393 | # Transformer tests |
|
394 | # Transformer tests | |
394 | def transform_checker(tests, func): |
|
395 | def transform_checker(tests, func): | |
395 | """Utility to loop over test inputs""" |
|
396 | """Utility to loop over test inputs""" | |
396 | for inp, tr in tests: |
|
397 | for inp, tr in tests: | |
397 | nt.assert_equals(func(inp), tr) |
|
398 | nt.assert_equals(func(inp), tr) | |
398 |
|
399 | |||
399 | # Data for all the syntax tests in the form of lists of pairs of |
|
400 | # Data for all the syntax tests in the form of lists of pairs of | |
400 | # raw/transformed input. We store it here as a global dict so that we can use |
|
401 | # raw/transformed input. We store it here as a global dict so that we can use | |
401 | # it both within single-function tests and also to validate the behavior of the |
|
402 | # it both within single-function tests and also to validate the behavior of the | |
402 | # larger objects |
|
403 | # larger objects | |
403 |
|
404 | |||
404 | syntax = \ |
|
405 | syntax = \ | |
405 | dict(assign_system = |
|
406 | dict(assign_system = | |
406 | [('a =! ls', 'a = get_ipython().getoutput(u"ls")'), |
|
407 | [(i,py3compat.u_format(o)) for i,o in \ | |
407 |
|
|
408 | [('a =! ls', 'a = get_ipython().getoutput({u}"ls")'), | |
|
409 | ('b = !ls', 'b = get_ipython().getoutput({u}"ls")'), | |||
408 | ('x=1', 'x=1'), # normal input is unmodified |
|
410 | ('x=1', 'x=1'), # normal input is unmodified | |
409 | (' ',' '), # blank lines are kept intact |
|
411 | (' ',' '), # blank lines are kept intact | |
410 | ], |
|
412 | ]], | |
411 |
|
413 | |||
412 | assign_magic = |
|
414 | assign_magic = | |
413 | [('a =% who', 'a = get_ipython().magic(u"who")'), |
|
415 | [(i,py3compat.u_format(o)) for i,o in \ | |
414 |
|
|
416 | [('a =% who', 'a = get_ipython().magic({u}"who")'), | |
|
417 | ('b = %who', 'b = get_ipython().magic({u}"who")'), | |||
415 | ('x=1', 'x=1'), # normal input is unmodified |
|
418 | ('x=1', 'x=1'), # normal input is unmodified | |
416 | (' ',' '), # blank lines are kept intact |
|
419 | (' ',' '), # blank lines are kept intact | |
417 | ], |
|
420 | ]], | |
418 |
|
421 | |||
419 | classic_prompt = |
|
422 | classic_prompt = | |
420 | [('>>> x=1', 'x=1'), |
|
423 | [('>>> x=1', 'x=1'), | |
421 | ('x=1', 'x=1'), # normal input is unmodified |
|
424 | ('x=1', 'x=1'), # normal input is unmodified | |
422 | (' ', ' '), # blank lines are kept intact |
|
425 | (' ', ' '), # blank lines are kept intact | |
423 | ('... ', ''), # continuation prompts |
|
426 | ('... ', ''), # continuation prompts | |
424 | ], |
|
427 | ], | |
425 |
|
428 | |||
426 | ipy_prompt = |
|
429 | ipy_prompt = | |
427 | [('In [1]: x=1', 'x=1'), |
|
430 | [('In [1]: x=1', 'x=1'), | |
428 | ('x=1', 'x=1'), # normal input is unmodified |
|
431 | ('x=1', 'x=1'), # normal input is unmodified | |
429 | (' ',' '), # blank lines are kept intact |
|
432 | (' ',' '), # blank lines are kept intact | |
430 | (' ....: ', ''), # continuation prompts |
|
433 | (' ....: ', ''), # continuation prompts | |
431 | ], |
|
434 | ], | |
432 |
|
435 | |||
433 | # Tests for the escape transformer to leave normal code alone |
|
436 | # Tests for the escape transformer to leave normal code alone | |
434 | escaped_noesc = |
|
437 | escaped_noesc = | |
435 | [ (' ', ' '), |
|
438 | [ (' ', ' '), | |
436 | ('x=1', 'x=1'), |
|
439 | ('x=1', 'x=1'), | |
437 | ], |
|
440 | ], | |
438 |
|
441 | |||
439 | # System calls |
|
442 | # System calls | |
440 | escaped_shell = |
|
443 | escaped_shell = | |
441 | [ ('!ls', 'get_ipython().system(u"ls")'), |
|
444 | [(i,py3compat.u_format(o)) for i,o in \ | |
|
445 | [ ('!ls', 'get_ipython().system({u}"ls")'), | |||
442 | # Double-escape shell, this means to capture the output of the |
|
446 | # Double-escape shell, this means to capture the output of the | |
443 | # subprocess and return it |
|
447 | # subprocess and return it | |
444 | ('!!ls', 'get_ipython().getoutput(u"ls")'), |
|
448 | ('!!ls', 'get_ipython().getoutput({u}"ls")'), | |
445 | ], |
|
449 | ]], | |
446 |
|
450 | |||
447 | # Help/object info |
|
451 | # Help/object info | |
448 | escaped_help = |
|
452 | escaped_help = | |
|
453 | [(i,py3compat.u_format(o)) for i,o in \ | |||
449 | [ ('?', 'get_ipython().show_usage()'), |
|
454 | [ ('?', 'get_ipython().show_usage()'), | |
450 | ('?x1', 'get_ipython().magic(u"pinfo x1")'), |
|
455 | ('?x1', 'get_ipython().magic({u}"pinfo x1")'), | |
451 | ('??x2', 'get_ipython().magic(u"pinfo2 x2")'), |
|
456 | ('??x2', 'get_ipython().magic({u}"pinfo2 x2")'), | |
452 | ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'), |
|
457 | ('?a.*s', 'get_ipython().magic({u}"psearch a.*s")'), | |
453 | ('?%hist', 'get_ipython().magic(u"pinfo %hist")'), |
|
458 | ('?%hist', 'get_ipython().magic({u}"pinfo %hist")'), | |
454 | ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'), |
|
459 | ('?abc = qwe', 'get_ipython().magic({u}"pinfo abc")'), | |
455 | ], |
|
460 | ]], | |
456 |
|
461 | |||
457 | end_help = |
|
462 | end_help = | |
458 | [ ('x3?', 'get_ipython().magic(u"pinfo x3")'), |
|
463 | [(i,py3compat.u_format(o)) for i,o in \ | |
459 |
|
|
464 | [ ('x3?', 'get_ipython().magic({u}"pinfo x3")'), | |
460 |
(' |
|
465 | ('x4??', 'get_ipython().magic({u}"pinfo2 x4")'), | |
461 |
(' |
|
466 | ('%hist?', 'get_ipython().magic({u}"pinfo %hist")'), | |
462 |
(' |
|
467 | ('f*?', 'get_ipython().magic({u}"psearch f*")'), | |
463 |
('a |
|
468 | ('ax.*aspe*?', 'get_ipython().magic({u}"psearch ax.*aspe*")'), | |
464 |
('a = abc |
|
469 | ('a = abc?', 'get_ipython().magic({u}"pinfo abc", next_input={u}"a = abc")'), | |
465 |
('a = |
|
470 | ('a = abc.qe??', 'get_ipython().magic({u}"pinfo2 abc.qe", next_input={u}"a = abc.qe")'), | |
466 |
(' |
|
471 | ('a = *.items?', 'get_ipython().magic({u}"psearch *.items", next_input={u}"a = *.items")'), | |
|
472 | ('plot(a?', 'get_ipython().magic({u}"pinfo a", next_input={u}"plot(a")'), | |||
467 | ('a*2 #comment?', 'a*2 #comment?'), |
|
473 | ('a*2 #comment?', 'a*2 #comment?'), | |
468 | ], |
|
474 | ]], | |
469 |
|
475 | |||
470 | # Explicit magic calls |
|
476 | # Explicit magic calls | |
471 | escaped_magic = |
|
477 | escaped_magic = | |
472 | [ ('%cd', 'get_ipython().magic(u"cd")'), |
|
478 | [(i,py3compat.u_format(o)) for i,o in \ | |
473 |
|
|
479 | [ ('%cd', 'get_ipython().magic({u}"cd")'), | |
474 |
(' |
|
480 | ('%cd /home', 'get_ipython().magic({u}"cd /home")'), | |
475 | ], |
|
481 | (' %magic', ' get_ipython().magic({u}"magic")'), | |
|
482 | ]], | |||
476 |
|
483 | |||
477 | # Quoting with separate arguments |
|
484 | # Quoting with separate arguments | |
478 | escaped_quote = |
|
485 | escaped_quote = | |
479 | [ (',f', 'f("")'), |
|
486 | [ (',f', 'f("")'), | |
480 | (',f x', 'f("x")'), |
|
487 | (',f x', 'f("x")'), | |
481 | (' ,f y', ' f("y")'), |
|
488 | (' ,f y', ' f("y")'), | |
482 | (',f a b', 'f("a", "b")'), |
|
489 | (',f a b', 'f("a", "b")'), | |
483 | ], |
|
490 | ], | |
484 |
|
491 | |||
485 | # Quoting with single argument |
|
492 | # Quoting with single argument | |
486 | escaped_quote2 = |
|
493 | escaped_quote2 = | |
487 | [ (';f', 'f("")'), |
|
494 | [ (';f', 'f("")'), | |
488 | (';f x', 'f("x")'), |
|
495 | (';f x', 'f("x")'), | |
489 | (' ;f y', ' f("y")'), |
|
496 | (' ;f y', ' f("y")'), | |
490 | (';f a b', 'f("a b")'), |
|
497 | (';f a b', 'f("a b")'), | |
491 | ], |
|
498 | ], | |
492 |
|
499 | |||
493 | # Simply apply parens |
|
500 | # Simply apply parens | |
494 | escaped_paren = |
|
501 | escaped_paren = | |
495 | [ ('/f', 'f()'), |
|
502 | [ ('/f', 'f()'), | |
496 | ('/f x', 'f(x)'), |
|
503 | ('/f x', 'f(x)'), | |
497 | (' /f y', ' f(y)'), |
|
504 | (' /f y', ' f(y)'), | |
498 | ('/f a b', 'f(a, b)'), |
|
505 | ('/f a b', 'f(a, b)'), | |
499 | ], |
|
506 | ], | |
500 |
|
507 | |||
501 | # Check that we transform prompts before other transforms |
|
508 | # Check that we transform prompts before other transforms | |
502 | mixed = |
|
509 | mixed = | |
503 | [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'), |
|
510 | [(i,py3compat.u_format(o)) for i,o in \ | |
504 |
|
|
511 | [ ('In [1]: %lsmagic', 'get_ipython().magic({u}"lsmagic")'), | |
505 |
(' |
|
512 | ('>>> %lsmagic', 'get_ipython().magic({u}"lsmagic")'), | |
506 |
('In [ |
|
513 | ('In [2]: !ls', 'get_ipython().system({u}"ls")'), | |
507 |
('In [ |
|
514 | ('In [3]: abs?', 'get_ipython().magic({u}"pinfo abs")'), | |
508 | ], |
|
515 | ('In [4]: b = %who', 'b = get_ipython().magic({u}"who")'), | |
|
516 | ]], | |||
509 | ) |
|
517 | ) | |
510 |
|
518 | |||
511 | # multiline syntax examples. Each of these should be a list of lists, with |
|
519 | # multiline syntax examples. Each of these should be a list of lists, with | |
512 | # each entry itself having pairs of raw/transformed input. The union (with |
|
520 | # each entry itself having pairs of raw/transformed input. The union (with | |
513 | # '\n'.join() of the transformed inputs is what the splitter should produce |
|
521 | # '\n'.join() of the transformed inputs is what the splitter should produce | |
514 | # when fed the raw lines one at a time via push. |
|
522 | # when fed the raw lines one at a time via push. | |
515 | syntax_ml = \ |
|
523 | syntax_ml = \ | |
516 | dict(classic_prompt = |
|
524 | dict(classic_prompt = | |
517 | [ [('>>> for i in range(10):','for i in range(10):'), |
|
525 | [ [('>>> for i in range(10):','for i in range(10):'), | |
518 | ('... print i',' print i'), |
|
526 | ('... print i',' print i'), | |
519 | ('... ', ''), |
|
527 | ('... ', ''), | |
520 | ], |
|
528 | ], | |
521 | ], |
|
529 | ], | |
522 |
|
530 | |||
523 | ipy_prompt = |
|
531 | ipy_prompt = | |
524 | [ [('In [24]: for i in range(10):','for i in range(10):'), |
|
532 | [ [('In [24]: for i in range(10):','for i in range(10):'), | |
525 | (' ....: print i',' print i'), |
|
533 | (' ....: print i',' print i'), | |
526 | (' ....: ', ''), |
|
534 | (' ....: ', ''), | |
527 | ], |
|
535 | ], | |
528 | ], |
|
536 | ], | |
529 | ) |
|
537 | ) | |
530 |
|
538 | |||
531 |
|
539 | |||
532 | def test_assign_system(): |
|
540 | def test_assign_system(): | |
533 | tt.check_pairs(isp.transform_assign_system, syntax['assign_system']) |
|
541 | tt.check_pairs(isp.transform_assign_system, syntax['assign_system']) | |
534 |
|
542 | |||
535 |
|
543 | |||
536 | def test_assign_magic(): |
|
544 | def test_assign_magic(): | |
537 | tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic']) |
|
545 | tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic']) | |
538 |
|
546 | |||
539 |
|
547 | |||
540 | def test_classic_prompt(): |
|
548 | def test_classic_prompt(): | |
541 | transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt) |
|
549 | transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt) | |
542 | for example in syntax_ml['classic_prompt']: |
|
550 | for example in syntax_ml['classic_prompt']: | |
543 | transform_checker(example, isp.transform_classic_prompt) |
|
551 | transform_checker(example, isp.transform_classic_prompt) | |
544 |
|
552 | |||
545 |
|
553 | |||
546 | def test_ipy_prompt(): |
|
554 | def test_ipy_prompt(): | |
547 | transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt) |
|
555 | transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt) | |
548 | for example in syntax_ml['ipy_prompt']: |
|
556 | for example in syntax_ml['ipy_prompt']: | |
549 | transform_checker(example, isp.transform_ipy_prompt) |
|
557 | transform_checker(example, isp.transform_ipy_prompt) | |
550 |
|
558 | |||
551 | def test_end_help(): |
|
559 | def test_end_help(): | |
552 | tt.check_pairs(isp.transform_help_end, syntax['end_help']) |
|
560 | tt.check_pairs(isp.transform_help_end, syntax['end_help']) | |
553 |
|
561 | |||
554 | def test_escaped_noesc(): |
|
562 | def test_escaped_noesc(): | |
555 | tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc']) |
|
563 | tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc']) | |
556 |
|
564 | |||
557 |
|
565 | |||
558 | def test_escaped_shell(): |
|
566 | def test_escaped_shell(): | |
559 | tt.check_pairs(isp.transform_escaped, syntax['escaped_shell']) |
|
567 | tt.check_pairs(isp.transform_escaped, syntax['escaped_shell']) | |
560 |
|
568 | |||
561 |
|
569 | |||
562 | def test_escaped_help(): |
|
570 | def test_escaped_help(): | |
563 | tt.check_pairs(isp.transform_escaped, syntax['escaped_help']) |
|
571 | tt.check_pairs(isp.transform_escaped, syntax['escaped_help']) | |
564 |
|
572 | |||
565 |
|
573 | |||
566 | def test_escaped_magic(): |
|
574 | def test_escaped_magic(): | |
567 | tt.check_pairs(isp.transform_escaped, syntax['escaped_magic']) |
|
575 | tt.check_pairs(isp.transform_escaped, syntax['escaped_magic']) | |
568 |
|
576 | |||
569 |
|
577 | |||
570 | def test_escaped_quote(): |
|
578 | def test_escaped_quote(): | |
571 | tt.check_pairs(isp.transform_escaped, syntax['escaped_quote']) |
|
579 | tt.check_pairs(isp.transform_escaped, syntax['escaped_quote']) | |
572 |
|
580 | |||
573 |
|
581 | |||
574 | def test_escaped_quote2(): |
|
582 | def test_escaped_quote2(): | |
575 | tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2']) |
|
583 | tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2']) | |
576 |
|
584 | |||
577 |
|
585 | |||
578 | def test_escaped_paren(): |
|
586 | def test_escaped_paren(): | |
579 | tt.check_pairs(isp.transform_escaped, syntax['escaped_paren']) |
|
587 | tt.check_pairs(isp.transform_escaped, syntax['escaped_paren']) | |
580 |
|
588 | |||
581 |
|
589 | |||
582 | class IPythonInputTestCase(InputSplitterTestCase): |
|
590 | class IPythonInputTestCase(InputSplitterTestCase): | |
583 | """By just creating a new class whose .isp is a different instance, we |
|
591 | """By just creating a new class whose .isp is a different instance, we | |
584 | re-run the same test battery on the new input splitter. |
|
592 | re-run the same test battery on the new input splitter. | |
585 |
|
593 | |||
586 | In addition, this runs the tests over the syntax and syntax_ml dicts that |
|
594 | In addition, this runs the tests over the syntax and syntax_ml dicts that | |
587 | were tested by individual functions, as part of the OO interface. |
|
595 | were tested by individual functions, as part of the OO interface. | |
588 |
|
596 | |||
589 | It also makes some checks on the raw buffer storage. |
|
597 | It also makes some checks on the raw buffer storage. | |
590 | """ |
|
598 | """ | |
591 |
|
599 | |||
592 | def setUp(self): |
|
600 | def setUp(self): | |
593 | self.isp = isp.IPythonInputSplitter(input_mode='line') |
|
601 | self.isp = isp.IPythonInputSplitter(input_mode='line') | |
594 |
|
602 | |||
595 | def test_syntax(self): |
|
603 | def test_syntax(self): | |
596 | """Call all single-line syntax tests from the main object""" |
|
604 | """Call all single-line syntax tests from the main object""" | |
597 | isp = self.isp |
|
605 | isp = self.isp | |
598 | for example in syntax.itervalues(): |
|
606 | for example in syntax.itervalues(): | |
599 | for raw, out_t in example: |
|
607 | for raw, out_t in example: | |
600 | if raw.startswith(' '): |
|
608 | if raw.startswith(' '): | |
601 | continue |
|
609 | continue | |
602 |
|
610 | |||
603 | isp.push(raw) |
|
611 | isp.push(raw) | |
604 | out, out_raw = isp.source_raw_reset() |
|
612 | out, out_raw = isp.source_raw_reset() | |
605 | self.assertEqual(out.rstrip(), out_t, |
|
613 | self.assertEqual(out.rstrip(), out_t, | |
606 | tt.pair_fail_msg.format("inputsplitter",raw, out_t, out)) |
|
614 | tt.pair_fail_msg.format("inputsplitter",raw, out_t, out)) | |
607 | self.assertEqual(out_raw.rstrip(), raw.rstrip()) |
|
615 | self.assertEqual(out_raw.rstrip(), raw.rstrip()) | |
608 |
|
616 | |||
609 | def test_syntax_multiline(self): |
|
617 | def test_syntax_multiline(self): | |
610 | isp = self.isp |
|
618 | isp = self.isp | |
611 | for example in syntax_ml.itervalues(): |
|
619 | for example in syntax_ml.itervalues(): | |
612 | out_t_parts = [] |
|
620 | out_t_parts = [] | |
613 | raw_parts = [] |
|
621 | raw_parts = [] | |
614 | for line_pairs in example: |
|
622 | for line_pairs in example: | |
615 | for lraw, out_t_part in line_pairs: |
|
623 | for lraw, out_t_part in line_pairs: | |
616 | isp.push(lraw) |
|
624 | isp.push(lraw) | |
617 | out_t_parts.append(out_t_part) |
|
625 | out_t_parts.append(out_t_part) | |
618 | raw_parts.append(lraw) |
|
626 | raw_parts.append(lraw) | |
619 |
|
627 | |||
620 | out, out_raw = isp.source_raw_reset() |
|
628 | out, out_raw = isp.source_raw_reset() | |
621 | out_t = '\n'.join(out_t_parts).rstrip() |
|
629 | out_t = '\n'.join(out_t_parts).rstrip() | |
622 | raw = '\n'.join(raw_parts).rstrip() |
|
630 | raw = '\n'.join(raw_parts).rstrip() | |
623 | self.assertEqual(out.rstrip(), out_t) |
|
631 | self.assertEqual(out.rstrip(), out_t) | |
624 | self.assertEqual(out_raw.rstrip(), raw) |
|
632 | self.assertEqual(out_raw.rstrip(), raw) | |
625 |
|
633 | |||
626 |
|
634 | |||
627 | class BlockIPythonInputTestCase(IPythonInputTestCase): |
|
635 | class BlockIPythonInputTestCase(IPythonInputTestCase): | |
628 |
|
636 | |||
629 | # Deactivate tests that don't make sense for the block mode |
|
637 | # Deactivate tests that don't make sense for the block mode | |
630 | test_push3 = test_split = lambda s: None |
|
638 | test_push3 = test_split = lambda s: None | |
631 |
|
639 | |||
632 | def setUp(self): |
|
640 | def setUp(self): | |
633 | self.isp = isp.IPythonInputSplitter(input_mode='cell') |
|
641 | self.isp = isp.IPythonInputSplitter(input_mode='cell') | |
634 |
|
642 | |||
635 | def test_syntax_multiline(self): |
|
643 | def test_syntax_multiline(self): | |
636 | isp = self.isp |
|
644 | isp = self.isp | |
637 | for example in syntax_ml.itervalues(): |
|
645 | for example in syntax_ml.itervalues(): | |
638 | raw_parts = [] |
|
646 | raw_parts = [] | |
639 | out_t_parts = [] |
|
647 | out_t_parts = [] | |
640 | for line_pairs in example: |
|
648 | for line_pairs in example: | |
641 | for raw, out_t_part in line_pairs: |
|
649 | for raw, out_t_part in line_pairs: | |
642 | raw_parts.append(raw) |
|
650 | raw_parts.append(raw) | |
643 | out_t_parts.append(out_t_part) |
|
651 | out_t_parts.append(out_t_part) | |
644 |
|
652 | |||
645 | raw = '\n'.join(raw_parts) |
|
653 | raw = '\n'.join(raw_parts) | |
646 | out_t = '\n'.join(out_t_parts) |
|
654 | out_t = '\n'.join(out_t_parts) | |
647 |
|
655 | |||
648 | isp.push(raw) |
|
656 | isp.push(raw) | |
649 | out, out_raw = isp.source_raw_reset() |
|
657 | out, out_raw = isp.source_raw_reset() | |
650 | # Match ignoring trailing whitespace |
|
658 | # Match ignoring trailing whitespace | |
651 | self.assertEqual(out.rstrip(), out_t.rstrip()) |
|
659 | self.assertEqual(out.rstrip(), out_t.rstrip()) | |
652 | self.assertEqual(out_raw.rstrip(), raw.rstrip()) |
|
660 | self.assertEqual(out_raw.rstrip(), raw.rstrip()) | |
653 |
|
661 | |||
654 |
|
662 | |||
655 | #----------------------------------------------------------------------------- |
|
663 | #----------------------------------------------------------------------------- | |
656 | # Main - use as a script, mostly for developer experiments |
|
664 | # Main - use as a script, mostly for developer experiments | |
657 | #----------------------------------------------------------------------------- |
|
665 | #----------------------------------------------------------------------------- | |
658 |
|
666 | |||
659 | if __name__ == '__main__': |
|
667 | if __name__ == '__main__': | |
660 | # A simple demo for interactive experimentation. This code will not get |
|
668 | # A simple demo for interactive experimentation. This code will not get | |
661 | # picked up by any test suite. |
|
669 | # picked up by any test suite. | |
662 | from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter |
|
670 | from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter | |
663 |
|
671 | |||
664 | # configure here the syntax to use, prompt and whether to autoindent |
|
672 | # configure here the syntax to use, prompt and whether to autoindent | |
665 | #isp, start_prompt = InputSplitter(), '>>> ' |
|
673 | #isp, start_prompt = InputSplitter(), '>>> ' | |
666 | isp, start_prompt = IPythonInputSplitter(), 'In> ' |
|
674 | isp, start_prompt = IPythonInputSplitter(), 'In> ' | |
667 |
|
675 | |||
668 | autoindent = True |
|
676 | autoindent = True | |
669 | #autoindent = False |
|
677 | #autoindent = False | |
670 |
|
678 | |||
671 | try: |
|
679 | try: | |
672 | while True: |
|
680 | while True: | |
673 | prompt = start_prompt |
|
681 | prompt = start_prompt | |
674 | while isp.push_accepts_more(): |
|
682 | while isp.push_accepts_more(): | |
675 | indent = ' '*isp.indent_spaces |
|
683 | indent = ' '*isp.indent_spaces | |
676 | if autoindent: |
|
684 | if autoindent: | |
677 | line = indent + raw_input(prompt+indent) |
|
685 | line = indent + raw_input(prompt+indent) | |
678 | else: |
|
686 | else: | |
679 | line = raw_input(prompt) |
|
687 | line = raw_input(prompt) | |
680 | isp.push(line) |
|
688 | isp.push(line) | |
681 | prompt = '... ' |
|
689 | prompt = '... ' | |
682 |
|
690 | |||
683 | # Here we just return input so we can use it in a test suite, but a |
|
691 | # Here we just return input so we can use it in a test suite, but a | |
684 | # real interpreter would instead send it for execution somewhere. |
|
692 | # real interpreter would instead send it for execution somewhere. | |
685 | #src = isp.source; raise EOFError # dbg |
|
693 | #src = isp.source; raise EOFError # dbg | |
686 | src, raw = isp.source_raw_reset() |
|
694 | src, raw = isp.source_raw_reset() | |
687 | print 'Input source was:\n', src |
|
695 | print 'Input source was:\n', src | |
688 | print 'Raw source was:\n', raw |
|
696 | print 'Raw source was:\n', raw | |
689 | except EOFError: |
|
697 | except EOFError: | |
690 | print 'Bye' |
|
698 | print 'Bye' |
@@ -1,271 +1,271 b'' | |||||
1 | """Tests for the key interactiveshell module, where the main ipython class is defined. |
|
1 | """Tests for the key interactiveshell module, where the main ipython class is defined. | |
2 | """ |
|
2 | """ | |
3 | #----------------------------------------------------------------------------- |
|
3 | #----------------------------------------------------------------------------- | |
4 | # Module imports |
|
4 | # Module imports | |
5 | #----------------------------------------------------------------------------- |
|
5 | #----------------------------------------------------------------------------- | |
6 |
|
6 | |||
7 | # stdlib |
|
7 | # stdlib | |
8 | import os |
|
8 | import os | |
9 | import shutil |
|
9 | import shutil | |
10 | import tempfile |
|
10 | import tempfile | |
11 |
|
11 | |||
12 | # third party |
|
12 | # third party | |
13 | import nose.tools as nt |
|
13 | import nose.tools as nt | |
14 |
|
14 | |||
15 | # our own packages |
|
15 | # our own packages | |
16 | from IPython.testing import decorators as dec |
|
16 | from IPython.testing import decorators as dec | |
17 | from IPython.testing.globalipapp import get_ipython |
|
17 | from IPython.testing.globalipapp import get_ipython | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Globals |
|
20 | # Globals | |
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
22 |
|
22 | |||
23 | # Get the public instance of IPython |
|
23 | # Get the public instance of IPython | |
24 | ip = get_ipython() |
|
24 | ip = get_ipython() | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | # Test functions |
|
27 | # Test functions | |
28 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
29 |
|
29 | |||
30 | @dec.parametric |
|
30 | @dec.parametric | |
31 | def test_reset(): |
|
31 | def test_reset(): | |
32 | """reset must clear most namespaces.""" |
|
32 | """reset must clear most namespaces.""" | |
33 | # The number of variables in the private user_ns_hidden is not zero, but it |
|
33 | # The number of variables in the private user_ns_hidden is not zero, but it | |
34 | # should be constant regardless of what we do |
|
34 | # should be constant regardless of what we do | |
35 | nvars_config_ns = len(ip.user_ns_hidden) |
|
35 | nvars_config_ns = len(ip.user_ns_hidden) | |
36 |
|
36 | |||
37 | # Check that reset runs without error |
|
37 | # Check that reset runs without error | |
38 | ip.reset() |
|
38 | ip.reset() | |
39 |
|
39 | |||
40 | # Once we've reset it (to clear of any junk that might have been there from |
|
40 | # Once we've reset it (to clear of any junk that might have been there from | |
41 | # other tests, we can count how many variables are in the user's namespace |
|
41 | # other tests, we can count how many variables are in the user's namespace | |
42 | nvars_user_ns = len(ip.user_ns) |
|
42 | nvars_user_ns = len(ip.user_ns) | |
43 |
|
43 | |||
44 | # Now add a few variables to user_ns, and check that reset clears them |
|
44 | # Now add a few variables to user_ns, and check that reset clears them | |
45 | ip.user_ns['x'] = 1 |
|
45 | ip.user_ns['x'] = 1 | |
46 | ip.user_ns['y'] = 1 |
|
46 | ip.user_ns['y'] = 1 | |
47 | ip.reset() |
|
47 | ip.reset() | |
48 |
|
48 | |||
49 | # Finally, check that all namespaces have only as many variables as we |
|
49 | # Finally, check that all namespaces have only as many variables as we | |
50 | # expect to find in them: |
|
50 | # expect to find in them: | |
51 | for ns in ip.ns_refs_table: |
|
51 | for ns in ip.ns_refs_table: | |
52 | if ns is ip.user_ns: |
|
52 | if ns is ip.user_ns: | |
53 | nvars_expected = nvars_user_ns |
|
53 | nvars_expected = nvars_user_ns | |
54 | elif ns is ip.user_ns_hidden: |
|
54 | elif ns is ip.user_ns_hidden: | |
55 | nvars_expected = nvars_config_ns |
|
55 | nvars_expected = nvars_config_ns | |
56 | else: |
|
56 | else: | |
57 | nvars_expected = 0 |
|
57 | nvars_expected = 0 | |
58 |
|
58 | |||
59 | yield nt.assert_equals(len(ns), nvars_expected) |
|
59 | yield nt.assert_equals(len(ns), nvars_expected) | |
60 |
|
60 | |||
61 |
|
61 | |||
62 | # Tests for reporting of exceptions in various modes, handling of SystemExit, |
|
62 | # Tests for reporting of exceptions in various modes, handling of SystemExit, | |
63 | # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell. |
|
63 | # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell. | |
64 |
|
64 | |||
65 | def doctest_tb_plain(): |
|
65 | def doctest_tb_plain(): | |
66 | """ |
|
66 | """ | |
67 | In [18]: xmode plain |
|
67 | In [18]: xmode plain | |
68 | Exception reporting mode: Plain |
|
68 | Exception reporting mode: Plain | |
69 |
|
69 | |||
70 | In [19]: run simpleerr.py |
|
70 | In [19]: run simpleerr.py | |
71 | Traceback (most recent call last): |
|
71 | Traceback (most recent call last): | |
72 | ...line 32, in <module> |
|
72 | ...line 32, in <module> | |
73 | bar(mode) |
|
73 | bar(mode) | |
74 | ...line 16, in bar |
|
74 | ...line 16, in bar | |
75 | div0() |
|
75 | div0() | |
76 | ...line 8, in div0 |
|
76 | ...line 8, in div0 | |
77 | x/y |
|
77 | x/y | |
78 | ZeroDivisionError: ... |
|
78 | ZeroDivisionError: ... | |
79 | """ |
|
79 | """ | |
80 |
|
80 | |||
81 |
|
81 | |||
82 | def doctest_tb_context(): |
|
82 | def doctest_tb_context(): | |
83 | """ |
|
83 | """ | |
84 | In [3]: xmode context |
|
84 | In [3]: xmode context | |
85 | Exception reporting mode: Context |
|
85 | Exception reporting mode: Context | |
86 |
|
86 | |||
87 | In [4]: run simpleerr.py |
|
87 | In [4]: run simpleerr.py | |
88 | --------------------------------------------------------------------------- |
|
88 | --------------------------------------------------------------------------- | |
89 | ZeroDivisionError Traceback (most recent call last) |
|
89 | ZeroDivisionError Traceback (most recent call last) | |
90 | <BLANKLINE> |
|
90 | <BLANKLINE> | |
91 | ... in <module>() |
|
91 | ... in <module>() | |
92 | 30 mode = 'div' |
|
92 | 30 mode = 'div' | |
93 | 31 |
|
93 | 31 | |
94 | ---> 32 bar(mode) |
|
94 | ---> 32 bar(mode) | |
95 | <BLANKLINE> |
|
95 | <BLANKLINE> | |
96 | ... in bar(mode) |
|
96 | ... in bar(mode) | |
97 | 14 "bar" |
|
97 | 14 "bar" | |
98 | 15 if mode=='div': |
|
98 | 15 if mode=='div': | |
99 | ---> 16 div0() |
|
99 | ---> 16 div0() | |
100 | 17 elif mode=='exit': |
|
100 | 17 elif mode=='exit': | |
101 | 18 try: |
|
101 | 18 try: | |
102 | <BLANKLINE> |
|
102 | <BLANKLINE> | |
103 | ... in div0() |
|
103 | ... in div0() | |
104 | 6 x = 1 |
|
104 | 6 x = 1 | |
105 | 7 y = 0 |
|
105 | 7 y = 0 | |
106 | ----> 8 x/y |
|
106 | ----> 8 x/y | |
107 | 9 |
|
107 | 9 | |
108 | 10 def sysexit(stat, mode): |
|
108 | 10 def sysexit(stat, mode): | |
109 | <BLANKLINE> |
|
109 | <BLANKLINE> | |
110 | ZeroDivisionError: ... |
|
110 | ZeroDivisionError: ... | |
111 | """ |
|
111 | """ | |
112 |
|
112 | |||
113 |
|
113 | |||
114 | def doctest_tb_verbose(): |
|
114 | def doctest_tb_verbose(): | |
115 | """ |
|
115 | """ | |
116 | In [5]: xmode verbose |
|
116 | In [5]: xmode verbose | |
117 | Exception reporting mode: Verbose |
|
117 | Exception reporting mode: Verbose | |
118 |
|
118 | |||
119 | In [6]: run simpleerr.py |
|
119 | In [6]: run simpleerr.py | |
120 | --------------------------------------------------------------------------- |
|
120 | --------------------------------------------------------------------------- | |
121 | ZeroDivisionError Traceback (most recent call last) |
|
121 | ZeroDivisionError Traceback (most recent call last) | |
122 | <BLANKLINE> |
|
122 | <BLANKLINE> | |
123 | ... in <module>() |
|
123 | ... in <module>() | |
124 | 30 mode = 'div' |
|
124 | 30 mode = 'div' | |
125 | 31 |
|
125 | 31 | |
126 | ---> 32 bar(mode) |
|
126 | ---> 32 bar(mode) | |
127 | global bar = <function bar at ...> |
|
127 | global bar = <function bar at ...> | |
128 | global mode = 'div' |
|
128 | global mode = 'div' | |
129 | <BLANKLINE> |
|
129 | <BLANKLINE> | |
130 | ... in bar(mode='div') |
|
130 | ... in bar(mode='div') | |
131 | 14 "bar" |
|
131 | 14 "bar" | |
132 | 15 if mode=='div': |
|
132 | 15 if mode=='div': | |
133 | ---> 16 div0() |
|
133 | ---> 16 div0() | |
134 | global div0 = <function div0 at ...> |
|
134 | global div0 = <function div0 at ...> | |
135 | 17 elif mode=='exit': |
|
135 | 17 elif mode=='exit': | |
136 | 18 try: |
|
136 | 18 try: | |
137 | <BLANKLINE> |
|
137 | <BLANKLINE> | |
138 | ... in div0() |
|
138 | ... in div0() | |
139 | 6 x = 1 |
|
139 | 6 x = 1 | |
140 | 7 y = 0 |
|
140 | 7 y = 0 | |
141 | ----> 8 x/y |
|
141 | ----> 8 x/y | |
142 | x = 1 |
|
142 | x = 1 | |
143 | y = 0 |
|
143 | y = 0 | |
144 | 9 |
|
144 | 9 | |
145 | 10 def sysexit(stat, mode): |
|
145 | 10 def sysexit(stat, mode): | |
146 | <BLANKLINE> |
|
146 | <BLANKLINE> | |
147 | ZeroDivisionError: ... |
|
147 | ZeroDivisionError: ... | |
148 | """ |
|
148 | """ | |
149 |
|
149 | |||
150 |
|
150 | @py3compat.u_format | ||
151 | def doctest_tb_sysexit(): |
|
151 | def doctest_tb_sysexit(): | |
152 | """ |
|
152 | """ | |
153 | In [17]: %xmode plain |
|
153 | In [17]: %xmode plain | |
154 | Exception reporting mode: Plain |
|
154 | Exception reporting mode: Plain | |
155 |
|
155 | |||
156 | In [18]: %run simpleerr.py exit |
|
156 | In [18]: %run simpleerr.py exit | |
157 | An exception has occurred, use %tb to see the full traceback. |
|
157 | An exception has occurred, use %tb to see the full traceback. | |
158 | SystemExit: (1, u'Mode = exit') |
|
158 | SystemExit: (1, {u}'Mode = exit') | |
159 |
|
159 | |||
160 | In [19]: %run simpleerr.py exit 2 |
|
160 | In [19]: %run simpleerr.py exit 2 | |
161 | An exception has occurred, use %tb to see the full traceback. |
|
161 | An exception has occurred, use %tb to see the full traceback. | |
162 | SystemExit: (2, u'Mode = exit') |
|
162 | SystemExit: (2, {u}'Mode = exit') | |
163 |
|
163 | |||
164 | In [20]: %tb |
|
164 | In [20]: %tb | |
165 | Traceback (most recent call last): |
|
165 | Traceback (most recent call last): | |
166 | File ... in <module> |
|
166 | File ... in <module> | |
167 | bar(mode) |
|
167 | bar(mode) | |
168 | File ... line 22, in bar |
|
168 | File ... line 22, in bar | |
169 | sysexit(stat, mode) |
|
169 | sysexit(stat, mode) | |
170 | File ... line 11, in sysexit |
|
170 | File ... line 11, in sysexit | |
171 | raise SystemExit(stat, 'Mode = %s' % mode) |
|
171 | raise SystemExit(stat, 'Mode = %s' % mode) | |
172 | SystemExit: (2, u'Mode = exit') |
|
172 | SystemExit: (2, {u}'Mode = exit') | |
173 |
|
173 | |||
174 | In [21]: %xmode context |
|
174 | In [21]: %xmode context | |
175 | Exception reporting mode: Context |
|
175 | Exception reporting mode: Context | |
176 |
|
176 | |||
177 | In [22]: %tb |
|
177 | In [22]: %tb | |
178 | --------------------------------------------------------------------------- |
|
178 | --------------------------------------------------------------------------- | |
179 | SystemExit Traceback (most recent call last) |
|
179 | SystemExit Traceback (most recent call last) | |
180 | <BLANKLINE> |
|
180 | <BLANKLINE> | |
181 | ...<module>() |
|
181 | ...<module>() | |
182 | 30 mode = 'div' |
|
182 | 30 mode = 'div' | |
183 | 31 |
|
183 | 31 | |
184 | ---> 32 bar(mode) |
|
184 | ---> 32 bar(mode) | |
185 | <BLANKLINE> |
|
185 | <BLANKLINE> | |
186 | ...bar(mode) |
|
186 | ...bar(mode) | |
187 | 20 except: |
|
187 | 20 except: | |
188 | 21 stat = 1 |
|
188 | 21 stat = 1 | |
189 | ---> 22 sysexit(stat, mode) |
|
189 | ---> 22 sysexit(stat, mode) | |
190 | 23 else: |
|
190 | 23 else: | |
191 | 24 raise ValueError('Unknown mode') |
|
191 | 24 raise ValueError('Unknown mode') | |
192 | <BLANKLINE> |
|
192 | <BLANKLINE> | |
193 | ...sysexit(stat, mode) |
|
193 | ...sysexit(stat, mode) | |
194 | 9 |
|
194 | 9 | |
195 | 10 def sysexit(stat, mode): |
|
195 | 10 def sysexit(stat, mode): | |
196 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) |
|
196 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) | |
197 | 12 |
|
197 | 12 | |
198 | 13 def bar(mode): |
|
198 | 13 def bar(mode): | |
199 | <BLANKLINE> |
|
199 | <BLANKLINE> | |
200 | SystemExit: (2, u'Mode = exit') |
|
200 | SystemExit: (2, {u}'Mode = exit') | |
201 |
|
201 | |||
202 | In [23]: %xmode verbose |
|
202 | In [23]: %xmode verbose | |
203 | Exception reporting mode: Verbose |
|
203 | Exception reporting mode: Verbose | |
204 |
|
204 | |||
205 | In [24]: %tb |
|
205 | In [24]: %tb | |
206 | --------------------------------------------------------------------------- |
|
206 | --------------------------------------------------------------------------- | |
207 | SystemExit Traceback (most recent call last) |
|
207 | SystemExit Traceback (most recent call last) | |
208 | <BLANKLINE> |
|
208 | <BLANKLINE> | |
209 | ... in <module>() |
|
209 | ... in <module>() | |
210 | 30 mode = 'div' |
|
210 | 30 mode = 'div' | |
211 | 31 |
|
211 | 31 | |
212 | ---> 32 bar(mode) |
|
212 | ---> 32 bar(mode) | |
213 | global bar = <function bar at ...> |
|
213 | global bar = <function bar at ...> | |
214 | global mode = u'exit' |
|
214 | global mode = {u}'exit' | |
215 | <BLANKLINE> |
|
215 | <BLANKLINE> | |
216 | ... in bar(mode=u'exit') |
|
216 | ... in bar(mode={u}'exit') | |
217 | 20 except: |
|
217 | 20 except: | |
218 | 21 stat = 1 |
|
218 | 21 stat = 1 | |
219 | ---> 22 sysexit(stat, mode) |
|
219 | ---> 22 sysexit(stat, mode) | |
220 | global sysexit = <function sysexit at ...> |
|
220 | global sysexit = <function sysexit at ...> | |
221 | stat = 2 |
|
221 | stat = 2 | |
222 | mode = u'exit' |
|
222 | mode = {u}'exit' | |
223 | 23 else: |
|
223 | 23 else: | |
224 | 24 raise ValueError('Unknown mode') |
|
224 | 24 raise ValueError('Unknown mode') | |
225 | <BLANKLINE> |
|
225 | <BLANKLINE> | |
226 | ... in sysexit(stat=2, mode=u'exit') |
|
226 | ... in sysexit(stat=2, mode={u}'exit') | |
227 | 9 |
|
227 | 9 | |
228 | 10 def sysexit(stat, mode): |
|
228 | 10 def sysexit(stat, mode): | |
229 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) |
|
229 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) | |
230 | global SystemExit = undefined |
|
230 | global SystemExit = undefined | |
231 | stat = 2 |
|
231 | stat = 2 | |
232 | mode = u'exit' |
|
232 | mode = {u}'exit' | |
233 | 12 |
|
233 | 12 | |
234 | 13 def bar(mode): |
|
234 | 13 def bar(mode): | |
235 | <BLANKLINE> |
|
235 | <BLANKLINE> | |
236 | SystemExit: (2, u'Mode = exit') |
|
236 | SystemExit: (2, {u}'Mode = exit') | |
237 | """ |
|
237 | """ | |
238 |
|
238 | |||
239 |
|
239 | |||
240 | def test_run_cell(): |
|
240 | def test_run_cell(): | |
241 | import textwrap |
|
241 | import textwrap | |
242 | ip.run_cell('a = 10\na+=1') |
|
242 | ip.run_cell('a = 10\na+=1') | |
243 | ip.run_cell('assert a == 11\nassert 1') |
|
243 | ip.run_cell('assert a == 11\nassert 1') | |
244 |
|
244 | |||
245 | nt.assert_equals(ip.user_ns['a'], 11) |
|
245 | nt.assert_equals(ip.user_ns['a'], 11) | |
246 | complex = textwrap.dedent(""" |
|
246 | complex = textwrap.dedent(""" | |
247 | if 1: |
|
247 | if 1: | |
248 | print "hello" |
|
248 | print "hello" | |
249 | if 1: |
|
249 | if 1: | |
250 | print "world" |
|
250 | print "world" | |
251 |
|
251 | |||
252 | if 2: |
|
252 | if 2: | |
253 | print "foo" |
|
253 | print "foo" | |
254 |
|
254 | |||
255 | if 3: |
|
255 | if 3: | |
256 | print "bar" |
|
256 | print "bar" | |
257 |
|
257 | |||
258 | if 4: |
|
258 | if 4: | |
259 | print "bar" |
|
259 | print "bar" | |
260 |
|
260 | |||
261 | """) |
|
261 | """) | |
262 | # Simply verifies that this kind of input is run |
|
262 | # Simply verifies that this kind of input is run | |
263 | ip.run_cell(complex) |
|
263 | ip.run_cell(complex) | |
264 |
|
264 | |||
265 |
|
265 | |||
266 | def test_db(): |
|
266 | def test_db(): | |
267 | """Test the internal database used for variable persistence.""" |
|
267 | """Test the internal database used for variable persistence.""" | |
268 | ip.db['__unittest_'] = 12 |
|
268 | ip.db['__unittest_'] = 12 | |
269 | nt.assert_equals(ip.db['__unittest_'], 12) |
|
269 | nt.assert_equals(ip.db['__unittest_'], 12) | |
270 | del ip.db['__unittest_'] |
|
270 | del ip.db['__unittest_'] | |
271 | assert '__unittest_' not in ip.db |
|
271 | assert '__unittest_' not in ip.db |
@@ -1,462 +1,467 b'' | |||||
1 | """Tests for various magic functions. |
|
1 | """Tests for various magic functions. | |
2 |
|
2 | |||
3 | Needs to be run by nose (to make ipython session available). |
|
3 | Needs to be run by nose (to make ipython session available). | |
4 | """ |
|
4 | """ | |
5 | from __future__ import absolute_import |
|
5 | from __future__ import absolute_import | |
6 |
|
6 | |||
7 | #----------------------------------------------------------------------------- |
|
7 | #----------------------------------------------------------------------------- | |
8 | # Imports |
|
8 | # Imports | |
9 | #----------------------------------------------------------------------------- |
|
9 | #----------------------------------------------------------------------------- | |
10 |
|
10 | |||
11 | import os |
|
11 | import os | |
12 | import sys |
|
12 | import sys | |
13 | import tempfile |
|
13 | import tempfile | |
14 | import types |
|
14 | import types | |
15 | from StringIO import StringIO |
|
15 | from StringIO import StringIO | |
16 |
|
16 | |||
17 | import nose.tools as nt |
|
17 | import nose.tools as nt | |
18 |
|
18 | |||
19 | from IPython.utils.path import get_long_path_name |
|
19 | from IPython.utils.path import get_long_path_name | |
20 | from IPython.testing import decorators as dec |
|
20 | from IPython.testing import decorators as dec | |
21 | from IPython.testing import tools as tt |
|
21 | from IPython.testing import tools as tt | |
|
22 | from IPython.utils import py3compat | |||
22 |
|
23 | |||
23 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
24 | # Test functions begin |
|
25 | # Test functions begin | |
25 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
26 | def test_rehashx(): |
|
27 | def test_rehashx(): | |
27 | # clear up everything |
|
28 | # clear up everything | |
28 | _ip = get_ipython() |
|
29 | _ip = get_ipython() | |
29 | _ip.alias_manager.alias_table.clear() |
|
30 | _ip.alias_manager.alias_table.clear() | |
30 | del _ip.db['syscmdlist'] |
|
31 | del _ip.db['syscmdlist'] | |
31 |
|
32 | |||
32 | _ip.magic('rehashx') |
|
33 | _ip.magic('rehashx') | |
33 | # Practically ALL ipython development systems will have more than 10 aliases |
|
34 | # Practically ALL ipython development systems will have more than 10 aliases | |
34 |
|
35 | |||
35 | yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10) |
|
36 | yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10) | |
36 | for key, val in _ip.alias_manager.alias_table.iteritems(): |
|
37 | for key, val in _ip.alias_manager.alias_table.iteritems(): | |
37 | # we must strip dots from alias names |
|
38 | # we must strip dots from alias names | |
38 | nt.assert_true('.' not in key) |
|
39 | nt.assert_true('.' not in key) | |
39 |
|
40 | |||
40 | # rehashx must fill up syscmdlist |
|
41 | # rehashx must fill up syscmdlist | |
41 | scoms = _ip.db['syscmdlist'] |
|
42 | scoms = _ip.db['syscmdlist'] | |
42 | yield (nt.assert_true, len(scoms) > 10) |
|
43 | yield (nt.assert_true, len(scoms) > 10) | |
43 |
|
44 | |||
44 |
|
45 | |||
45 | def test_magic_parse_options(): |
|
46 | def test_magic_parse_options(): | |
46 | """Test that we don't mangle paths when parsing magic options.""" |
|
47 | """Test that we don't mangle paths when parsing magic options.""" | |
47 | ip = get_ipython() |
|
48 | ip = get_ipython() | |
48 | path = 'c:\\x' |
|
49 | path = 'c:\\x' | |
49 | opts = ip.parse_options('-f %s' % path,'f:')[0] |
|
50 | opts = ip.parse_options('-f %s' % path,'f:')[0] | |
50 | # argv splitting is os-dependent |
|
51 | # argv splitting is os-dependent | |
51 | if os.name == 'posix': |
|
52 | if os.name == 'posix': | |
52 | expected = 'c:x' |
|
53 | expected = 'c:x' | |
53 | else: |
|
54 | else: | |
54 | expected = path |
|
55 | expected = path | |
55 | nt.assert_equals(opts['f'], expected) |
|
56 | nt.assert_equals(opts['f'], expected) | |
56 |
|
57 | |||
57 |
|
58 | |||
58 | def doctest_hist_f(): |
|
59 | def doctest_hist_f(): | |
59 | """Test %hist -f with temporary filename. |
|
60 | """Test %hist -f with temporary filename. | |
60 |
|
61 | |||
61 | In [9]: import tempfile |
|
62 | In [9]: import tempfile | |
62 |
|
63 | |||
63 | In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') |
|
64 | In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') | |
64 |
|
65 | |||
65 | In [11]: %hist -nl -f $tfile 3 |
|
66 | In [11]: %hist -nl -f $tfile 3 | |
66 |
|
67 | |||
67 | In [13]: import os; os.unlink(tfile) |
|
68 | In [13]: import os; os.unlink(tfile) | |
68 | """ |
|
69 | """ | |
69 |
|
70 | |||
70 |
|
71 | |||
71 | def doctest_hist_r(): |
|
72 | def doctest_hist_r(): | |
72 | """Test %hist -r |
|
73 | """Test %hist -r | |
73 |
|
74 | |||
74 | XXX - This test is not recording the output correctly. For some reason, in |
|
75 | XXX - This test is not recording the output correctly. For some reason, in | |
75 | testing mode the raw history isn't getting populated. No idea why. |
|
76 | testing mode the raw history isn't getting populated. No idea why. | |
76 | Disabling the output checking for now, though at least we do run it. |
|
77 | Disabling the output checking for now, though at least we do run it. | |
77 |
|
78 | |||
78 | In [1]: 'hist' in _ip.lsmagic() |
|
79 | In [1]: 'hist' in _ip.lsmagic() | |
79 | Out[1]: True |
|
80 | Out[1]: True | |
80 |
|
81 | |||
81 | In [2]: x=1 |
|
82 | In [2]: x=1 | |
82 |
|
83 | |||
83 | In [3]: %hist -rl 2 |
|
84 | In [3]: %hist -rl 2 | |
84 | x=1 # random |
|
85 | x=1 # random | |
85 | %hist -r 2 |
|
86 | %hist -r 2 | |
86 | """ |
|
87 | """ | |
87 |
|
88 | |||
88 | def doctest_hist_op(): |
|
89 | def doctest_hist_op(): | |
89 | """Test %hist -op |
|
90 | """Test %hist -op | |
90 |
|
91 | |||
91 | In [1]: class b: |
|
92 | In [1]: class b(float): | |
92 |
...: |
|
93 | ...: pass | |
93 | ...: |
|
94 | ...: | |
94 |
|
95 | |||
95 | In [2]: class s(b): |
|
96 | In [2]: class s(object): | |
96 |
...: |
|
97 | ...: def __str__(self): | |
97 |
...: |
|
98 | ...: return 's' | |
98 | ...: |
|
99 | ...: | |
99 |
|
100 | |||
100 | In [3]: |
|
101 | In [3]: | |
101 |
|
102 | |||
102 | In [4]: class r(b): |
|
103 | In [4]: class r(b): | |
103 |
...: |
|
104 | ...: def __repr__(self): | |
104 |
...: |
|
105 | ...: return 'r' | |
105 | ...: |
|
106 | ...: | |
106 |
|
107 | |||
107 | In [5]: class sr(s,r): pass |
|
108 | In [5]: class sr(s,r): pass | |
108 | ...: |
|
109 | ...: | |
109 |
|
110 | |||
110 | In [6]: |
|
111 | In [6]: | |
111 |
|
112 | |||
112 | In [7]: bb=b() |
|
113 | In [7]: bb=b() | |
113 |
|
114 | |||
114 | In [8]: ss=s() |
|
115 | In [8]: ss=s() | |
115 |
|
116 | |||
116 | In [9]: rr=r() |
|
117 | In [9]: rr=r() | |
117 |
|
118 | |||
118 | In [10]: ssrr=sr() |
|
119 | In [10]: ssrr=sr() | |
119 |
|
120 | |||
120 |
In [11]: |
|
121 | In [11]: 4.5 | |
121 | Out[11]: <...b instance at ...> |
|
122 | Out[11]: 4.5 | |
122 |
|
123 | |||
123 | In [12]: ss |
|
124 | In [12]: str(ss) | |
124 | Out[12]: <...s instance at ...> |
|
125 | Out[12]: 's' | |
125 |
|
126 | |||
126 | In [13]: |
|
127 | In [13]: | |
127 |
|
128 | |||
128 | In [14]: %hist -op |
|
129 | In [14]: %hist -op | |
129 | >>> class b: |
|
130 | >>> class b: | |
130 | ... pass |
|
131 | ... pass | |
131 | ... |
|
132 | ... | |
132 | >>> class s(b): |
|
133 | >>> class s(b): | |
133 | ... def __str__(self): |
|
134 | ... def __str__(self): | |
134 | ... return 's' |
|
135 | ... return 's' | |
135 | ... |
|
136 | ... | |
136 | >>> |
|
137 | >>> | |
137 | >>> class r(b): |
|
138 | >>> class r(b): | |
138 | ... def __repr__(self): |
|
139 | ... def __repr__(self): | |
139 | ... return 'r' |
|
140 | ... return 'r' | |
140 | ... |
|
141 | ... | |
141 | >>> class sr(s,r): pass |
|
142 | >>> class sr(s,r): pass | |
142 | >>> |
|
143 | >>> | |
143 | >>> bb=b() |
|
144 | >>> bb=b() | |
144 | >>> ss=s() |
|
145 | >>> ss=s() | |
145 | >>> rr=r() |
|
146 | >>> rr=r() | |
146 | >>> ssrr=sr() |
|
147 | >>> ssrr=sr() | |
147 |
>>> |
|
148 | >>> 4.5 | |
148 | <...b instance at ...> |
|
149 | 4.5 | |
149 | >>> ss |
|
150 | >>> str(ss) | |
150 | <...s instance at ...> |
|
151 | 's' | |
151 | >>> |
|
152 | >>> | |
152 | """ |
|
153 | """ | |
153 |
|
154 | |||
154 | def test_macro(): |
|
155 | def test_macro(): | |
155 | ip = get_ipython() |
|
156 | ip = get_ipython() | |
156 | ip.history_manager.reset() # Clear any existing history. |
|
157 | ip.history_manager.reset() # Clear any existing history. | |
157 | cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] |
|
158 | cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] | |
158 | for i, cmd in enumerate(cmds, start=1): |
|
159 | for i, cmd in enumerate(cmds, start=1): | |
159 | ip.history_manager.store_inputs(i, cmd) |
|
160 | ip.history_manager.store_inputs(i, cmd) | |
160 | ip.magic("macro test 1-3") |
|
161 | ip.magic("macro test 1-3") | |
161 | nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n") |
|
162 | nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n") | |
162 |
|
163 | |||
163 | # List macros. |
|
164 | # List macros. | |
164 | assert "test" in ip.magic("macro") |
|
165 | assert "test" in ip.magic("macro") | |
165 |
|
166 | |||
166 | def test_macro_run(): |
|
167 | def test_macro_run(): | |
167 | """Test that we can run a multi-line macro successfully.""" |
|
168 | """Test that we can run a multi-line macro successfully.""" | |
168 | ip = get_ipython() |
|
169 | ip = get_ipython() | |
169 | ip.history_manager.reset() |
|
170 | ip.history_manager.reset() | |
170 | cmds = ["a=10", "a+=1", "print a", "%macro test 2-3"] |
|
171 | cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"), | |
|
172 | "%macro test 2-3"] | |||
171 | for cmd in cmds: |
|
173 | for cmd in cmds: | |
172 | ip.run_cell(cmd) |
|
174 | ip.run_cell(cmd) | |
173 |
nt.assert_equal(ip.user_ns["test"].value, |
|
175 | nt.assert_equal(ip.user_ns["test"].value, | |
|
176 | py3compat.doctest_refactor_print("a+=1\nprint a\n")) | |||
174 | original_stdout = sys.stdout |
|
177 | original_stdout = sys.stdout | |
175 | new_stdout = StringIO() |
|
178 | new_stdout = StringIO() | |
176 | sys.stdout = new_stdout |
|
179 | sys.stdout = new_stdout | |
177 | try: |
|
180 | try: | |
178 | ip.run_cell("test") |
|
181 | ip.run_cell("test") | |
179 | nt.assert_true("12" in new_stdout.getvalue()) |
|
182 | nt.assert_true("12" in new_stdout.getvalue()) | |
180 | ip.run_cell("test") |
|
183 | ip.run_cell("test") | |
181 | nt.assert_true("13" in new_stdout.getvalue()) |
|
184 | nt.assert_true("13" in new_stdout.getvalue()) | |
182 | finally: |
|
185 | finally: | |
183 | sys.stdout = original_stdout |
|
186 | sys.stdout = original_stdout | |
184 | new_stdout.close() |
|
187 | new_stdout.close() | |
185 |
|
188 | |||
186 |
|
189 | |||
187 | # XXX failing for now, until we get clearcmd out of quarantine. But we should |
|
190 | # XXX failing for now, until we get clearcmd out of quarantine. But we should | |
188 | # fix this and revert the skip to happen only if numpy is not around. |
|
191 | # fix this and revert the skip to happen only if numpy is not around. | |
189 | #@dec.skipif_not_numpy |
|
192 | #@dec.skipif_not_numpy | |
190 | @dec.skip_known_failure |
|
193 | @dec.skip_known_failure | |
191 | def test_numpy_clear_array_undec(): |
|
194 | def test_numpy_clear_array_undec(): | |
192 | from IPython.extensions import clearcmd |
|
195 | from IPython.extensions import clearcmd | |
193 |
|
196 | |||
194 | _ip.ex('import numpy as np') |
|
197 | _ip.ex('import numpy as np') | |
195 | _ip.ex('a = np.empty(2)') |
|
198 | _ip.ex('a = np.empty(2)') | |
196 | yield (nt.assert_true, 'a' in _ip.user_ns) |
|
199 | yield (nt.assert_true, 'a' in _ip.user_ns) | |
197 | _ip.magic('clear array') |
|
200 | _ip.magic('clear array') | |
198 | yield (nt.assert_false, 'a' in _ip.user_ns) |
|
201 | yield (nt.assert_false, 'a' in _ip.user_ns) | |
199 |
|
202 | |||
200 |
|
203 | |||
201 | # Multiple tests for clipboard pasting |
|
204 | # Multiple tests for clipboard pasting | |
202 | @dec.parametric |
|
205 | @dec.parametric | |
203 | def test_paste(): |
|
206 | def test_paste(): | |
204 | _ip = get_ipython() |
|
207 | _ip = get_ipython() | |
205 | def paste(txt, flags='-q'): |
|
208 | def paste(txt, flags='-q'): | |
206 | """Paste input text, by default in quiet mode""" |
|
209 | """Paste input text, by default in quiet mode""" | |
207 | hooks.clipboard_get = lambda : txt |
|
210 | hooks.clipboard_get = lambda : txt | |
208 | _ip.magic('paste '+flags) |
|
211 | _ip.magic('paste '+flags) | |
209 |
|
212 | |||
210 | # Inject fake clipboard hook but save original so we can restore it later |
|
213 | # Inject fake clipboard hook but save original so we can restore it later | |
211 | hooks = _ip.hooks |
|
214 | hooks = _ip.hooks | |
212 | user_ns = _ip.user_ns |
|
215 | user_ns = _ip.user_ns | |
213 | original_clip = hooks.clipboard_get |
|
216 | original_clip = hooks.clipboard_get | |
214 |
|
217 | |||
215 | try: |
|
218 | try: | |
216 | # This try/except with an emtpy except clause is here only because |
|
219 | # This try/except with an emtpy except clause is here only because | |
217 | # try/yield/finally is invalid syntax in Python 2.4. This will be |
|
220 | # try/yield/finally is invalid syntax in Python 2.4. This will be | |
218 | # removed when we drop 2.4-compatibility, and the emtpy except below |
|
221 | # removed when we drop 2.4-compatibility, and the emtpy except below | |
219 | # will be changed to a finally. |
|
222 | # will be changed to a finally. | |
220 |
|
223 | |||
221 | # Run tests with fake clipboard function |
|
224 | # Run tests with fake clipboard function | |
222 | user_ns.pop('x', None) |
|
225 | user_ns.pop('x', None) | |
223 | paste('x=1') |
|
226 | paste('x=1') | |
224 | yield nt.assert_equal(user_ns['x'], 1) |
|
227 | yield nt.assert_equal(user_ns['x'], 1) | |
225 |
|
228 | |||
226 | user_ns.pop('x', None) |
|
229 | user_ns.pop('x', None) | |
227 | paste('>>> x=2') |
|
230 | paste('>>> x=2') | |
228 | yield nt.assert_equal(user_ns['x'], 2) |
|
231 | yield nt.assert_equal(user_ns['x'], 2) | |
229 |
|
232 | |||
230 | paste(""" |
|
233 | paste(""" | |
231 | >>> x = [1,2,3] |
|
234 | >>> x = [1,2,3] | |
232 | >>> y = [] |
|
235 | >>> y = [] | |
233 | >>> for i in x: |
|
236 | >>> for i in x: | |
234 | ... y.append(i**2) |
|
237 | ... y.append(i**2) | |
235 | ... |
|
238 | ... | |
236 | """) |
|
239 | """) | |
237 | yield nt.assert_equal(user_ns['x'], [1,2,3]) |
|
240 | yield nt.assert_equal(user_ns['x'], [1,2,3]) | |
238 | yield nt.assert_equal(user_ns['y'], [1,4,9]) |
|
241 | yield nt.assert_equal(user_ns['y'], [1,4,9]) | |
239 |
|
242 | |||
240 | # Now, test that paste -r works |
|
243 | # Now, test that paste -r works | |
241 | user_ns.pop('x', None) |
|
244 | user_ns.pop('x', None) | |
242 | yield nt.assert_false('x' in user_ns) |
|
245 | yield nt.assert_false('x' in user_ns) | |
243 | _ip.magic('paste -r') |
|
246 | _ip.magic('paste -r') | |
244 | yield nt.assert_equal(user_ns['x'], [1,2,3]) |
|
247 | yield nt.assert_equal(user_ns['x'], [1,2,3]) | |
245 |
|
248 | |||
246 | # Also test paste echoing, by temporarily faking the writer |
|
249 | # Also test paste echoing, by temporarily faking the writer | |
247 | w = StringIO() |
|
250 | w = StringIO() | |
248 | writer = _ip.write |
|
251 | writer = _ip.write | |
249 | _ip.write = w.write |
|
252 | _ip.write = w.write | |
250 | code = """ |
|
253 | code = """ | |
251 | a = 100 |
|
254 | a = 100 | |
252 | b = 200""" |
|
255 | b = 200""" | |
253 | try: |
|
256 | try: | |
254 | paste(code,'') |
|
257 | paste(code,'') | |
255 | out = w.getvalue() |
|
258 | out = w.getvalue() | |
256 | finally: |
|
259 | finally: | |
257 | _ip.write = writer |
|
260 | _ip.write = writer | |
258 | yield nt.assert_equal(user_ns['a'], 100) |
|
261 | yield nt.assert_equal(user_ns['a'], 100) | |
259 | yield nt.assert_equal(user_ns['b'], 200) |
|
262 | yield nt.assert_equal(user_ns['b'], 200) | |
260 | yield nt.assert_equal(out, code+"\n## -- End pasted text --\n") |
|
263 | yield nt.assert_equal(out, code+"\n## -- End pasted text --\n") | |
261 |
|
264 | |||
262 | finally: |
|
265 | finally: | |
263 | # This should be in a finally clause, instead of the bare except above. |
|
266 | # This should be in a finally clause, instead of the bare except above. | |
264 | # Restore original hook |
|
267 | # Restore original hook | |
265 | hooks.clipboard_get = original_clip |
|
268 | hooks.clipboard_get = original_clip | |
266 |
|
269 | |||
267 |
|
270 | |||
268 | def test_time(): |
|
271 | def test_time(): | |
269 | _ip.magic('time None') |
|
272 | _ip.magic('time None') | |
270 |
|
273 | |||
271 |
|
274 | |||
|
275 | @py3compat.doctest_refactor_print | |||
272 | def doctest_time(): |
|
276 | def doctest_time(): | |
273 | """ |
|
277 | """ | |
274 | In [10]: %time None |
|
278 | In [10]: %time None | |
275 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
279 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
276 | Wall time: 0.00 s |
|
280 | Wall time: 0.00 s | |
277 |
|
281 | |||
278 | In [11]: def f(kmjy): |
|
282 | In [11]: def f(kmjy): | |
279 | ....: %time print 2*kmjy |
|
283 | ....: %time print 2*kmjy | |
280 |
|
284 | |||
281 | In [12]: f(3) |
|
285 | In [12]: f(3) | |
282 | 6 |
|
286 | 6 | |
283 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
287 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
284 | Wall time: 0.00 s |
|
288 | Wall time: 0.00 s | |
285 | """ |
|
289 | """ | |
286 |
|
290 | |||
287 |
|
291 | |||
288 | def test_doctest_mode(): |
|
292 | def test_doctest_mode(): | |
289 | "Toggle doctest_mode twice, it should be a no-op and run without error" |
|
293 | "Toggle doctest_mode twice, it should be a no-op and run without error" | |
290 | _ip.magic('doctest_mode') |
|
294 | _ip.magic('doctest_mode') | |
291 | _ip.magic('doctest_mode') |
|
295 | _ip.magic('doctest_mode') | |
292 |
|
296 | |||
293 |
|
297 | |||
294 | def test_parse_options(): |
|
298 | def test_parse_options(): | |
295 | """Tests for basic options parsing in magics.""" |
|
299 | """Tests for basic options parsing in magics.""" | |
296 | # These are only the most minimal of tests, more should be added later. At |
|
300 | # These are only the most minimal of tests, more should be added later. At | |
297 | # the very least we check that basic text/unicode calls work OK. |
|
301 | # the very least we check that basic text/unicode calls work OK. | |
298 | nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo') |
|
302 | nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo') | |
299 | nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo') |
|
303 | nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo') | |
300 |
|
304 | |||
301 |
|
305 | |||
302 | def test_dirops(): |
|
306 | def test_dirops(): | |
303 | """Test various directory handling operations.""" |
|
307 | """Test various directory handling operations.""" | |
304 | # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/') |
|
308 | # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/') | |
305 | curpath = os.getcwdu |
|
309 | curpath = os.getcwdu | |
306 | startdir = os.getcwdu() |
|
310 | startdir = os.getcwdu() | |
307 | ipdir = _ip.ipython_dir |
|
311 | ipdir = _ip.ipython_dir | |
308 | try: |
|
312 | try: | |
309 | _ip.magic('cd "%s"' % ipdir) |
|
313 | _ip.magic('cd "%s"' % ipdir) | |
310 | nt.assert_equal(curpath(), ipdir) |
|
314 | nt.assert_equal(curpath(), ipdir) | |
311 | _ip.magic('cd -') |
|
315 | _ip.magic('cd -') | |
312 | nt.assert_equal(curpath(), startdir) |
|
316 | nt.assert_equal(curpath(), startdir) | |
313 | _ip.magic('pushd "%s"' % ipdir) |
|
317 | _ip.magic('pushd "%s"' % ipdir) | |
314 | nt.assert_equal(curpath(), ipdir) |
|
318 | nt.assert_equal(curpath(), ipdir) | |
315 | _ip.magic('popd') |
|
319 | _ip.magic('popd') | |
316 | nt.assert_equal(curpath(), startdir) |
|
320 | nt.assert_equal(curpath(), startdir) | |
317 | finally: |
|
321 | finally: | |
318 | os.chdir(startdir) |
|
322 | os.chdir(startdir) | |
319 |
|
323 | |||
320 |
|
324 | |||
321 | def check_cpaste(code, should_fail=False): |
|
325 | def check_cpaste(code, should_fail=False): | |
322 | """Execute code via 'cpaste' and ensure it was executed, unless |
|
326 | """Execute code via 'cpaste' and ensure it was executed, unless | |
323 | should_fail is set. |
|
327 | should_fail is set. | |
324 | """ |
|
328 | """ | |
325 | _ip.user_ns['code_ran'] = False |
|
329 | _ip.user_ns['code_ran'] = False | |
326 |
|
330 | |||
327 | src = StringIO() |
|
331 | src = StringIO() | |
328 | src.write('\n') |
|
332 | src.write('\n') | |
329 | src.write(code) |
|
333 | src.write(code) | |
330 | src.write('\n--\n') |
|
334 | src.write('\n--\n') | |
331 | src.seek(0) |
|
335 | src.seek(0) | |
332 |
|
336 | |||
333 | stdin_save = sys.stdin |
|
337 | stdin_save = sys.stdin | |
334 | sys.stdin = src |
|
338 | sys.stdin = src | |
335 |
|
339 | |||
336 | try: |
|
340 | try: | |
337 | _ip.magic('cpaste') |
|
341 | _ip.magic('cpaste') | |
338 | except: |
|
342 | except: | |
339 | if not should_fail: |
|
343 | if not should_fail: | |
340 | raise AssertionError("Failure not expected : '%s'" % |
|
344 | raise AssertionError("Failure not expected : '%s'" % | |
341 | code) |
|
345 | code) | |
342 | else: |
|
346 | else: | |
343 | assert _ip.user_ns['code_ran'] |
|
347 | assert _ip.user_ns['code_ran'] | |
344 | if should_fail: |
|
348 | if should_fail: | |
345 | raise AssertionError("Failure expected : '%s'" % code) |
|
349 | raise AssertionError("Failure expected : '%s'" % code) | |
346 | finally: |
|
350 | finally: | |
347 | sys.stdin = stdin_save |
|
351 | sys.stdin = stdin_save | |
348 |
|
352 | |||
349 |
|
353 | |||
350 | def test_cpaste(): |
|
354 | def test_cpaste(): | |
351 | """Test cpaste magic""" |
|
355 | """Test cpaste magic""" | |
352 |
|
356 | |||
353 | def run(): |
|
357 | def run(): | |
354 | """Marker function: sets a flag when executed. |
|
358 | """Marker function: sets a flag when executed. | |
355 | """ |
|
359 | """ | |
356 | _ip.user_ns['code_ran'] = True |
|
360 | _ip.user_ns['code_ran'] = True | |
357 | return 'run' # return string so '+ run()' doesn't result in success |
|
361 | return 'run' # return string so '+ run()' doesn't result in success | |
358 |
|
362 | |||
359 | tests = {'pass': ["> > > run()", |
|
363 | tests = {'pass': ["> > > run()", | |
360 | ">>> > run()", |
|
364 | ">>> > run()", | |
361 | "+++ run()", |
|
365 | "+++ run()", | |
362 | "++ run()", |
|
366 | "++ run()", | |
363 | " >>> run()"], |
|
367 | " >>> run()"], | |
364 |
|
368 | |||
365 | 'fail': ["+ + run()", |
|
369 | 'fail': ["+ + run()", | |
366 | " ++ run()"]} |
|
370 | " ++ run()"]} | |
367 |
|
371 | |||
368 | _ip.user_ns['run'] = run |
|
372 | _ip.user_ns['run'] = run | |
369 |
|
373 | |||
370 | for code in tests['pass']: |
|
374 | for code in tests['pass']: | |
371 | check_cpaste(code) |
|
375 | check_cpaste(code) | |
372 |
|
376 | |||
373 | for code in tests['fail']: |
|
377 | for code in tests['fail']: | |
374 | check_cpaste(code, should_fail=True) |
|
378 | check_cpaste(code, should_fail=True) | |
375 |
|
379 | |||
376 | def test_xmode(): |
|
380 | def test_xmode(): | |
377 | # Calling xmode three times should be a no-op |
|
381 | # Calling xmode three times should be a no-op | |
378 | xmode = _ip.InteractiveTB.mode |
|
382 | xmode = _ip.InteractiveTB.mode | |
379 | for i in range(3): |
|
383 | for i in range(3): | |
380 | _ip.magic("xmode") |
|
384 | _ip.magic("xmode") | |
381 | nt.assert_equal(_ip.InteractiveTB.mode, xmode) |
|
385 | nt.assert_equal(_ip.InteractiveTB.mode, xmode) | |
382 |
|
386 | |||
383 | def test_reset_hard(): |
|
387 | def test_reset_hard(): | |
384 | monitor = [] |
|
388 | monitor = [] | |
385 | class A(object): |
|
389 | class A(object): | |
386 | def __del__(self): |
|
390 | def __del__(self): | |
387 | monitor.append(1) |
|
391 | monitor.append(1) | |
388 | def __repr__(self): |
|
392 | def __repr__(self): | |
389 | return "<A instance>" |
|
393 | return "<A instance>" | |
390 |
|
394 | |||
391 | _ip.user_ns["a"] = A() |
|
395 | _ip.user_ns["a"] = A() | |
392 | _ip.run_cell("a") |
|
396 | _ip.run_cell("a") | |
393 |
|
397 | |||
394 | nt.assert_equal(monitor, []) |
|
398 | nt.assert_equal(monitor, []) | |
395 | _ip.magic_reset("-f") |
|
399 | _ip.magic_reset("-f") | |
396 | nt.assert_equal(monitor, [1]) |
|
400 | nt.assert_equal(monitor, [1]) | |
397 |
|
401 | |||
398 | class TestXdel(tt.TempFileMixin): |
|
402 | class TestXdel(tt.TempFileMixin): | |
399 | def test_xdel(self): |
|
403 | def test_xdel(self): | |
400 | """Test that references from %run are cleared by xdel.""" |
|
404 | """Test that references from %run are cleared by xdel.""" | |
401 | src = ("class A(object):\n" |
|
405 | src = ("class A(object):\n" | |
402 | " monitor = []\n" |
|
406 | " monitor = []\n" | |
403 | " def __del__(self):\n" |
|
407 | " def __del__(self):\n" | |
404 | " self.monitor.append(1)\n" |
|
408 | " self.monitor.append(1)\n" | |
405 | "a = A()\n") |
|
409 | "a = A()\n") | |
406 | self.mktmp(src) |
|
410 | self.mktmp(src) | |
407 | # %run creates some hidden references... |
|
411 | # %run creates some hidden references... | |
408 | _ip.magic("run %s" % self.fname) |
|
412 | _ip.magic("run %s" % self.fname) | |
409 | # ... as does the displayhook. |
|
413 | # ... as does the displayhook. | |
410 | _ip.run_cell("a") |
|
414 | _ip.run_cell("a") | |
411 |
|
415 | |||
412 | monitor = _ip.user_ns["A"].monitor |
|
416 | monitor = _ip.user_ns["A"].monitor | |
413 | nt.assert_equal(monitor, []) |
|
417 | nt.assert_equal(monitor, []) | |
414 |
|
418 | |||
415 | _ip.magic("xdel a") |
|
419 | _ip.magic("xdel a") | |
416 |
|
420 | |||
417 | # Check that a's __del__ method has been called. |
|
421 | # Check that a's __del__ method has been called. | |
418 | nt.assert_equal(monitor, [1]) |
|
422 | nt.assert_equal(monitor, [1]) | |
419 |
|
423 | |||
420 | def doctest_who(): |
|
424 | def doctest_who(): | |
421 | """doctest for %who |
|
425 | """doctest for %who | |
422 |
|
426 | |||
423 | In [1]: %reset -f |
|
427 | In [1]: %reset -f | |
424 |
|
428 | |||
425 | In [2]: alpha = 123 |
|
429 | In [2]: alpha = 123 | |
426 |
|
430 | |||
427 | In [3]: beta = 'beta' |
|
431 | In [3]: beta = 'beta' | |
428 |
|
432 | |||
429 | In [4]: %who int |
|
433 | In [4]: %who int | |
430 | alpha |
|
434 | alpha | |
431 |
|
435 | |||
432 | In [5]: %who str |
|
436 | In [5]: %who str | |
433 | beta |
|
437 | beta | |
434 |
|
438 | |||
435 | In [6]: %whos |
|
439 | In [6]: %whos | |
436 | Variable Type Data/Info |
|
440 | Variable Type Data/Info | |
437 | ---------------------------- |
|
441 | ---------------------------- | |
438 | alpha int 123 |
|
442 | alpha int 123 | |
439 | beta str beta |
|
443 | beta str beta | |
440 |
|
444 | |||
441 | In [7]: %who_ls |
|
445 | In [7]: %who_ls | |
442 | Out[7]: ['alpha', 'beta'] |
|
446 | Out[7]: ['alpha', 'beta'] | |
443 | """ |
|
447 | """ | |
444 |
|
448 | |||
|
449 | @py3compat.u_format | |||
445 | def doctest_precision(): |
|
450 | def doctest_precision(): | |
446 | """doctest for %precision |
|
451 | """doctest for %precision | |
447 |
|
452 | |||
448 | In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain'] |
|
453 | In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain'] | |
449 |
|
454 | |||
450 | In [2]: %precision 5 |
|
455 | In [2]: %precision 5 | |
451 | Out[2]: u'%.5f' |
|
456 | Out[2]: {u}'%.5f' | |
452 |
|
457 | |||
453 | In [3]: f.float_format |
|
458 | In [3]: f.float_format | |
454 | Out[3]: u'%.5f' |
|
459 | Out[3]: {u}'%.5f' | |
455 |
|
460 | |||
456 | In [4]: %precision %e |
|
461 | In [4]: %precision %e | |
457 | Out[4]: u'%e' |
|
462 | Out[4]: {u}'%e' | |
458 |
|
463 | |||
459 | In [5]: f(3.1415927) |
|
464 | In [5]: f(3.1415927) | |
460 | Out[5]: u'3.141593e+00' |
|
465 | Out[5]: {u}'3.141593e+00' | |
461 | """ |
|
466 | """ | |
462 |
|
467 |
@@ -1,208 +1,210 b'' | |||||
1 | """Tests for code execution (%run and related), which is particularly tricky. |
|
1 | """Tests for code execution (%run and related), which is particularly tricky. | |
2 |
|
2 | |||
3 | Because of how %run manages namespaces, and the fact that we are trying here to |
|
3 | Because of how %run manages namespaces, and the fact that we are trying here to | |
4 | verify subtle object deletion and reference counting issues, the %run tests |
|
4 | verify subtle object deletion and reference counting issues, the %run tests | |
5 | will be kept in this separate file. This makes it easier to aggregate in one |
|
5 | will be kept in this separate file. This makes it easier to aggregate in one | |
6 | place the tricks needed to handle it; most other magics are much easier to test |
|
6 | place the tricks needed to handle it; most other magics are much easier to test | |
7 | and we do so in a common test_magic file. |
|
7 | and we do so in a common test_magic file. | |
8 | """ |
|
8 | """ | |
9 | from __future__ import absolute_import |
|
9 | from __future__ import absolute_import | |
10 |
|
10 | |||
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | # Imports |
|
12 | # Imports | |
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 |
|
14 | |||
15 | import os |
|
15 | import os | |
16 | import sys |
|
16 | import sys | |
17 | import tempfile |
|
17 | import tempfile | |
18 |
|
18 | |||
19 | import nose.tools as nt |
|
19 | import nose.tools as nt | |
20 | from nose import SkipTest |
|
20 | from nose import SkipTest | |
21 |
|
21 | |||
22 | from IPython.testing import decorators as dec |
|
22 | from IPython.testing import decorators as dec | |
23 | from IPython.testing import tools as tt |
|
23 | from IPython.testing import tools as tt | |
|
24 | from IPython.utils.py3compat import doctest_refactor_print | |||
24 |
|
25 | |||
25 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
26 | # Test functions begin |
|
27 | # Test functions begin | |
27 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
28 |
|
29 | |||
29 | def doctest_refbug(): |
|
30 | def doctest_refbug(): | |
30 | """Very nasty problem with references held by multiple runs of a script. |
|
31 | """Very nasty problem with references held by multiple runs of a script. | |
31 | See: https://github.com/ipython/ipython/issues/141 |
|
32 | See: https://github.com/ipython/ipython/issues/141 | |
32 |
|
33 | |||
33 | In [1]: _ip.clear_main_mod_cache() |
|
34 | In [1]: _ip.clear_main_mod_cache() | |
34 | # random |
|
35 | # random | |
35 |
|
36 | |||
36 | In [2]: %run refbug |
|
37 | In [2]: %run refbug | |
37 |
|
38 | |||
38 | In [3]: call_f() |
|
39 | In [3]: call_f() | |
39 | lowercased: hello |
|
40 | lowercased: hello | |
40 |
|
41 | |||
41 | In [4]: %run refbug |
|
42 | In [4]: %run refbug | |
42 |
|
43 | |||
43 | In [5]: call_f() |
|
44 | In [5]: call_f() | |
44 | lowercased: hello |
|
45 | lowercased: hello | |
45 | lowercased: hello |
|
46 | lowercased: hello | |
46 | """ |
|
47 | """ | |
47 |
|
48 | |||
48 |
|
49 | |||
49 | def doctest_run_builtins(): |
|
50 | def doctest_run_builtins(): | |
50 | r"""Check that %run doesn't damage __builtins__. |
|
51 | r"""Check that %run doesn't damage __builtins__. | |
51 |
|
52 | |||
52 | In [1]: import tempfile |
|
53 | In [1]: import tempfile | |
53 |
|
54 | |||
54 | In [2]: bid1 = id(__builtins__) |
|
55 | In [2]: bid1 = id(__builtins__) | |
55 |
|
56 | |||
56 | In [3]: fname = tempfile.mkstemp('.py')[1] |
|
57 | In [3]: fname = tempfile.mkstemp('.py')[1] | |
57 |
|
58 | |||
58 | In [3]: f = open(fname,'w') |
|
59 | In [3]: f = open(fname,'w') | |
59 |
|
60 | |||
60 | In [4]: f.write('pass\n') |
|
61 | In [4]: dummy= f.write('pass\n') | |
61 |
|
62 | |||
62 | In [5]: f.flush() |
|
63 | In [5]: f.flush() | |
63 |
|
64 | |||
64 | In [6]: t1 = type(__builtins__) |
|
65 | In [6]: t1 = type(__builtins__) | |
65 |
|
66 | |||
66 | In [7]: %run $fname |
|
67 | In [7]: %run $fname | |
67 |
|
68 | |||
68 | In [7]: f.close() |
|
69 | In [7]: f.close() | |
69 |
|
70 | |||
70 | In [8]: bid2 = id(__builtins__) |
|
71 | In [8]: bid2 = id(__builtins__) | |
71 |
|
72 | |||
72 | In [9]: t2 = type(__builtins__) |
|
73 | In [9]: t2 = type(__builtins__) | |
73 |
|
74 | |||
74 | In [10]: t1 == t2 |
|
75 | In [10]: t1 == t2 | |
75 | Out[10]: True |
|
76 | Out[10]: True | |
76 |
|
77 | |||
77 | In [10]: bid1 == bid2 |
|
78 | In [10]: bid1 == bid2 | |
78 | Out[10]: True |
|
79 | Out[10]: True | |
79 |
|
80 | |||
80 | In [12]: try: |
|
81 | In [12]: try: | |
81 | ....: os.unlink(fname) |
|
82 | ....: os.unlink(fname) | |
82 | ....: except: |
|
83 | ....: except: | |
83 | ....: pass |
|
84 | ....: pass | |
84 | ....: |
|
85 | ....: | |
85 | """ |
|
86 | """ | |
86 |
|
87 | |||
|
88 | @doctest_refactor_print | |||
87 | def doctest_reset_del(): |
|
89 | def doctest_reset_del(): | |
88 | """Test that resetting doesn't cause errors in __del__ methods. |
|
90 | """Test that resetting doesn't cause errors in __del__ methods. | |
89 |
|
91 | |||
90 | In [2]: class A(object): |
|
92 | In [2]: class A(object): | |
91 | ...: def __del__(self): |
|
93 | ...: def __del__(self): | |
92 | ...: print str("Hi") |
|
94 | ...: print str("Hi") | |
93 | ...: |
|
95 | ...: | |
94 |
|
96 | |||
95 | In [3]: a = A() |
|
97 | In [3]: a = A() | |
96 |
|
98 | |||
97 | In [4]: get_ipython().reset() |
|
99 | In [4]: get_ipython().reset() | |
98 | Hi |
|
100 | Hi | |
99 |
|
101 | |||
100 | In [5]: 1+1 |
|
102 | In [5]: 1+1 | |
101 | Out[5]: 2 |
|
103 | Out[5]: 2 | |
102 | """ |
|
104 | """ | |
103 |
|
105 | |||
104 | # For some tests, it will be handy to organize them in a class with a common |
|
106 | # For some tests, it will be handy to organize them in a class with a common | |
105 | # setup that makes a temp file |
|
107 | # setup that makes a temp file | |
106 |
|
108 | |||
107 | class TestMagicRunPass(tt.TempFileMixin): |
|
109 | class TestMagicRunPass(tt.TempFileMixin): | |
108 |
|
110 | |||
109 | def setup(self): |
|
111 | def setup(self): | |
110 | """Make a valid python temp file.""" |
|
112 | """Make a valid python temp file.""" | |
111 | self.mktmp('pass\n') |
|
113 | self.mktmp('pass\n') | |
112 |
|
114 | |||
113 | def run_tmpfile(self): |
|
115 | def run_tmpfile(self): | |
114 | _ip = get_ipython() |
|
116 | _ip = get_ipython() | |
115 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. |
|
117 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. | |
116 | # See below and ticket https://bugs.launchpad.net/bugs/366353 |
|
118 | # See below and ticket https://bugs.launchpad.net/bugs/366353 | |
117 | _ip.magic('run %s' % self.fname) |
|
119 | _ip.magic('run %s' % self.fname) | |
118 |
|
120 | |||
119 | def test_builtins_id(self): |
|
121 | def test_builtins_id(self): | |
120 | """Check that %run doesn't damage __builtins__ """ |
|
122 | """Check that %run doesn't damage __builtins__ """ | |
121 | _ip = get_ipython() |
|
123 | _ip = get_ipython() | |
122 | # Test that the id of __builtins__ is not modified by %run |
|
124 | # Test that the id of __builtins__ is not modified by %run | |
123 | bid1 = id(_ip.user_ns['__builtins__']) |
|
125 | bid1 = id(_ip.user_ns['__builtins__']) | |
124 | self.run_tmpfile() |
|
126 | self.run_tmpfile() | |
125 | bid2 = id(_ip.user_ns['__builtins__']) |
|
127 | bid2 = id(_ip.user_ns['__builtins__']) | |
126 | tt.assert_equals(bid1, bid2) |
|
128 | tt.assert_equals(bid1, bid2) | |
127 |
|
129 | |||
128 | def test_builtins_type(self): |
|
130 | def test_builtins_type(self): | |
129 | """Check that the type of __builtins__ doesn't change with %run. |
|
131 | """Check that the type of __builtins__ doesn't change with %run. | |
130 |
|
132 | |||
131 | However, the above could pass if __builtins__ was already modified to |
|
133 | However, the above could pass if __builtins__ was already modified to | |
132 | be a dict (it should be a module) by a previous use of %run. So we |
|
134 | be a dict (it should be a module) by a previous use of %run. So we | |
133 | also check explicitly that it really is a module: |
|
135 | also check explicitly that it really is a module: | |
134 | """ |
|
136 | """ | |
135 | _ip = get_ipython() |
|
137 | _ip = get_ipython() | |
136 | self.run_tmpfile() |
|
138 | self.run_tmpfile() | |
137 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) |
|
139 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) | |
138 |
|
140 | |||
139 | def test_prompts(self): |
|
141 | def test_prompts(self): | |
140 | """Test that prompts correctly generate after %run""" |
|
142 | """Test that prompts correctly generate after %run""" | |
141 | self.run_tmpfile() |
|
143 | self.run_tmpfile() | |
142 | _ip = get_ipython() |
|
144 | _ip = get_ipython() | |
143 | p2 = str(_ip.displayhook.prompt2).strip() |
|
145 | p2 = str(_ip.displayhook.prompt2).strip() | |
144 | nt.assert_equals(p2[:3], '...') |
|
146 | nt.assert_equals(p2[:3], '...') | |
145 |
|
147 | |||
146 |
|
148 | |||
147 | class TestMagicRunSimple(tt.TempFileMixin): |
|
149 | class TestMagicRunSimple(tt.TempFileMixin): | |
148 |
|
150 | |||
149 | def test_simpledef(self): |
|
151 | def test_simpledef(self): | |
150 | """Test that simple class definitions work.""" |
|
152 | """Test that simple class definitions work.""" | |
151 | src = ("class foo: pass\n" |
|
153 | src = ("class foo: pass\n" | |
152 | "def f(): return foo()") |
|
154 | "def f(): return foo()") | |
153 | self.mktmp(src) |
|
155 | self.mktmp(src) | |
154 | _ip.magic('run %s' % self.fname) |
|
156 | _ip.magic('run %s' % self.fname) | |
155 | _ip.run_cell('t = isinstance(f(), foo)') |
|
157 | _ip.run_cell('t = isinstance(f(), foo)') | |
156 | nt.assert_true(_ip.user_ns['t']) |
|
158 | nt.assert_true(_ip.user_ns['t']) | |
157 |
|
159 | |||
158 | def test_obj_del(self): |
|
160 | def test_obj_del(self): | |
159 | """Test that object's __del__ methods are called on exit.""" |
|
161 | """Test that object's __del__ methods are called on exit.""" | |
160 | if sys.platform == 'win32': |
|
162 | if sys.platform == 'win32': | |
161 | try: |
|
163 | try: | |
162 | import win32api |
|
164 | import win32api | |
163 | except ImportError: |
|
165 | except ImportError: | |
164 | raise SkipTest("Test requires pywin32") |
|
166 | raise SkipTest("Test requires pywin32") | |
165 | src = ("class A(object):\n" |
|
167 | src = ("class A(object):\n" | |
166 | " def __del__(self):\n" |
|
168 | " def __del__(self):\n" | |
167 | " print 'object A deleted'\n" |
|
169 | " print 'object A deleted'\n" | |
168 | "a = A()\n") |
|
170 | "a = A()\n") | |
169 | self.mktmp(src) |
|
171 | self.mktmp(src) | |
170 | tt.ipexec_validate(self.fname, 'object A deleted') |
|
172 | tt.ipexec_validate(self.fname, 'object A deleted') | |
171 |
|
173 | |||
172 | @dec.skip_known_failure |
|
174 | @dec.skip_known_failure | |
173 | def test_aggressive_namespace_cleanup(self): |
|
175 | def test_aggressive_namespace_cleanup(self): | |
174 | """Test that namespace cleanup is not too aggressive GH-238 |
|
176 | """Test that namespace cleanup is not too aggressive GH-238 | |
175 |
|
177 | |||
176 | Returning from another run magic deletes the namespace""" |
|
178 | Returning from another run magic deletes the namespace""" | |
177 | # see ticket https://github.com/ipython/ipython/issues/238 |
|
179 | # see ticket https://github.com/ipython/ipython/issues/238 | |
178 | class secondtmp(tt.TempFileMixin): pass |
|
180 | class secondtmp(tt.TempFileMixin): pass | |
179 | empty = secondtmp() |
|
181 | empty = secondtmp() | |
180 | empty.mktmp('') |
|
182 | empty.mktmp('') | |
181 | src = ("ip = get_ipython()\n" |
|
183 | src = ("ip = get_ipython()\n" | |
182 | "for i in range(5):\n" |
|
184 | "for i in range(5):\n" | |
183 | " try:\n" |
|
185 | " try:\n" | |
184 | " ip.magic('run %s')\n" |
|
186 | " ip.magic('run %s')\n" | |
185 | " except NameError, e:\n" |
|
187 | " except NameError, e:\n" | |
186 | " print i;break\n" % empty.fname) |
|
188 | " print i;break\n" % empty.fname) | |
187 | self.mktmp(src) |
|
189 | self.mktmp(src) | |
188 | _ip.magic('run %s' % self.fname) |
|
190 | _ip.magic('run %s' % self.fname) | |
189 | _ip.run_cell('ip == get_ipython()') |
|
191 | _ip.run_cell('ip == get_ipython()') | |
190 | tt.assert_equals(_ip.user_ns['i'], 5) |
|
192 | tt.assert_equals(_ip.user_ns['i'], 5) | |
191 |
|
193 | |||
192 | @dec.skip_win32 |
|
194 | @dec.skip_win32 | |
193 | def test_tclass(self): |
|
195 | def test_tclass(self): | |
194 | mydir = os.path.dirname(__file__) |
|
196 | mydir = os.path.dirname(__file__) | |
195 | tc = os.path.join(mydir, 'tclass') |
|
197 | tc = os.path.join(mydir, 'tclass') | |
196 | src = ("%%run '%s' C-first\n" |
|
198 | src = ("%%run '%s' C-first\n" | |
197 | "%%run '%s' C-second\n" |
|
199 | "%%run '%s' C-second\n" | |
198 | "%%run '%s' C-third\n") % (tc, tc, tc) |
|
200 | "%%run '%s' C-third\n") % (tc, tc, tc) | |
199 | self.mktmp(src, '.ipy') |
|
201 | self.mktmp(src, '.ipy') | |
200 | out = """\ |
|
202 | out = """\ | |
201 | ARGV 1-: [u'C-first'] |
|
203 | ARGV 1-: [u'C-first'] | |
202 | ARGV 1-: [u'C-second'] |
|
204 | ARGV 1-: [u'C-second'] | |
203 | tclass.py: deleting object: C-first |
|
205 | tclass.py: deleting object: C-first | |
204 | ARGV 1-: [u'C-third'] |
|
206 | ARGV 1-: [u'C-third'] | |
205 | tclass.py: deleting object: C-second |
|
207 | tclass.py: deleting object: C-second | |
206 | tclass.py: deleting object: C-third |
|
208 | tclass.py: deleting object: C-third | |
207 | """ |
|
209 | """ | |
208 | tt.ipexec_validate(self.fname, out) |
|
210 | tt.ipexec_validate(self.fname, out) |
General Comments 0
You need to be logged in to leave comments.
Login now