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