|
@@
-1,912
+1,932
b''
|
|
1
|
# -*- coding: utf-8 -*-
|
|
1
|
# -*- coding: utf-8 -*-
|
|
2
|
"""Tests for the key interactiveshell module.
|
|
2
|
"""Tests for the key interactiveshell module.
|
|
3
|
|
|
3
|
|
|
4
|
Historically the main classes in interactiveshell have been under-tested. This
|
|
4
|
Historically the main classes in interactiveshell have been under-tested. This
|
|
5
|
module should grow as many single-method tests as possible to trap many of the
|
|
5
|
module should grow as many single-method tests as possible to trap many of the
|
|
6
|
recurring bugs we seem to encounter with high-level interaction.
|
|
6
|
recurring bugs we seem to encounter with high-level interaction.
|
|
7
|
"""
|
|
7
|
"""
|
|
8
|
|
|
8
|
|
|
9
|
# Copyright (c) IPython Development Team.
|
|
9
|
# Copyright (c) IPython Development Team.
|
|
10
|
# Distributed under the terms of the Modified BSD License.
|
|
10
|
# Distributed under the terms of the Modified BSD License.
|
|
11
|
|
|
11
|
|
|
12
|
import ast
|
|
12
|
import ast
|
|
13
|
import os
|
|
13
|
import os
|
|
14
|
import signal
|
|
14
|
import signal
|
|
15
|
import shutil
|
|
15
|
import shutil
|
|
16
|
import sys
|
|
16
|
import sys
|
|
17
|
import tempfile
|
|
17
|
import tempfile
|
|
18
|
import unittest
|
|
18
|
import unittest
|
|
19
|
from unittest import mock
|
|
19
|
from unittest import mock
|
|
20
|
from io import StringIO
|
|
20
|
from io import StringIO
|
|
21
|
|
|
21
|
|
|
22
|
from os.path import join
|
|
22
|
from os.path import join
|
|
23
|
|
|
23
|
|
|
24
|
import nose.tools as nt
|
|
24
|
import nose.tools as nt
|
|
25
|
|
|
25
|
|
|
26
|
from IPython.core.error import InputRejected
|
|
26
|
from IPython.core.error import InputRejected
|
|
27
|
from IPython.core.inputtransformer import InputTransformer
|
|
27
|
from IPython.core.inputtransformer import InputTransformer
|
|
28
|
from IPython.testing.decorators import (
|
|
28
|
from IPython.testing.decorators import (
|
|
29
|
skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
|
|
29
|
skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
|
|
30
|
)
|
|
30
|
)
|
|
31
|
from IPython.testing import tools as tt
|
|
31
|
from IPython.testing import tools as tt
|
|
32
|
from IPython.utils.process import find_cmd
|
|
32
|
from IPython.utils.process import find_cmd
|
|
33
|
from IPython.utils import py3compat
|
|
33
|
from IPython.utils import py3compat
|
|
34
|
|
|
34
|
|
|
35
|
#-----------------------------------------------------------------------------
|
|
35
|
#-----------------------------------------------------------------------------
|
|
36
|
# Globals
|
|
36
|
# Globals
|
|
37
|
#-----------------------------------------------------------------------------
|
|
37
|
#-----------------------------------------------------------------------------
|
|
38
|
# This is used by every single test, no point repeating it ad nauseam
|
|
38
|
# This is used by every single test, no point repeating it ad nauseam
|
|
39
|
ip = get_ipython()
|
|
39
|
ip = get_ipython()
|
|
40
|
|
|
40
|
|
|
41
|
#-----------------------------------------------------------------------------
|
|
41
|
#-----------------------------------------------------------------------------
|
|
42
|
# Tests
|
|
42
|
# Tests
|
|
43
|
#-----------------------------------------------------------------------------
|
|
43
|
#-----------------------------------------------------------------------------
|
|
44
|
|
|
44
|
|
|
45
|
class DerivedInterrupt(KeyboardInterrupt):
|
|
45
|
class DerivedInterrupt(KeyboardInterrupt):
|
|
46
|
pass
|
|
46
|
pass
|
|
47
|
|
|
47
|
|
|
48
|
class InteractiveShellTestCase(unittest.TestCase):
|
|
48
|
class InteractiveShellTestCase(unittest.TestCase):
|
|
49
|
def test_naked_string_cells(self):
|
|
49
|
def test_naked_string_cells(self):
|
|
50
|
"""Test that cells with only naked strings are fully executed"""
|
|
50
|
"""Test that cells with only naked strings are fully executed"""
|
|
51
|
# First, single-line inputs
|
|
51
|
# First, single-line inputs
|
|
52
|
ip.run_cell('"a"\n')
|
|
52
|
ip.run_cell('"a"\n')
|
|
53
|
self.assertEqual(ip.user_ns['_'], 'a')
|
|
53
|
self.assertEqual(ip.user_ns['_'], 'a')
|
|
54
|
# And also multi-line cells
|
|
54
|
# And also multi-line cells
|
|
55
|
ip.run_cell('"""a\nb"""\n')
|
|
55
|
ip.run_cell('"""a\nb"""\n')
|
|
56
|
self.assertEqual(ip.user_ns['_'], 'a\nb')
|
|
56
|
self.assertEqual(ip.user_ns['_'], 'a\nb')
|
|
57
|
|
|
57
|
|
|
58
|
def test_run_empty_cell(self):
|
|
58
|
def test_run_empty_cell(self):
|
|
59
|
"""Just make sure we don't get a horrible error with a blank
|
|
59
|
"""Just make sure we don't get a horrible error with a blank
|
|
60
|
cell of input. Yes, I did overlook that."""
|
|
60
|
cell of input. Yes, I did overlook that."""
|
|
61
|
old_xc = ip.execution_count
|
|
61
|
old_xc = ip.execution_count
|
|
62
|
res = ip.run_cell('')
|
|
62
|
res = ip.run_cell('')
|
|
63
|
self.assertEqual(ip.execution_count, old_xc)
|
|
63
|
self.assertEqual(ip.execution_count, old_xc)
|
|
64
|
self.assertEqual(res.execution_count, None)
|
|
64
|
self.assertEqual(res.execution_count, None)
|
|
65
|
|
|
65
|
|
|
66
|
def test_run_cell_multiline(self):
|
|
66
|
def test_run_cell_multiline(self):
|
|
67
|
"""Multi-block, multi-line cells must execute correctly.
|
|
67
|
"""Multi-block, multi-line cells must execute correctly.
|
|
68
|
"""
|
|
68
|
"""
|
|
69
|
src = '\n'.join(["x=1",
|
|
69
|
src = '\n'.join(["x=1",
|
|
70
|
"y=2",
|
|
70
|
"y=2",
|
|
71
|
"if 1:",
|
|
71
|
"if 1:",
|
|
72
|
" x += 1",
|
|
72
|
" x += 1",
|
|
73
|
" y += 1",])
|
|
73
|
" y += 1",])
|
|
74
|
res = ip.run_cell(src)
|
|
74
|
res = ip.run_cell(src)
|
|
75
|
self.assertEqual(ip.user_ns['x'], 2)
|
|
75
|
self.assertEqual(ip.user_ns['x'], 2)
|
|
76
|
self.assertEqual(ip.user_ns['y'], 3)
|
|
76
|
self.assertEqual(ip.user_ns['y'], 3)
|
|
77
|
self.assertEqual(res.success, True)
|
|
77
|
self.assertEqual(res.success, True)
|
|
78
|
self.assertEqual(res.result, None)
|
|
78
|
self.assertEqual(res.result, None)
|
|
79
|
|
|
79
|
|
|
80
|
def test_multiline_string_cells(self):
|
|
80
|
def test_multiline_string_cells(self):
|
|
81
|
"Code sprinkled with multiline strings should execute (GH-306)"
|
|
81
|
"Code sprinkled with multiline strings should execute (GH-306)"
|
|
82
|
ip.run_cell('tmp=0')
|
|
82
|
ip.run_cell('tmp=0')
|
|
83
|
self.assertEqual(ip.user_ns['tmp'], 0)
|
|
83
|
self.assertEqual(ip.user_ns['tmp'], 0)
|
|
84
|
res = ip.run_cell('tmp=1;"""a\nb"""\n')
|
|
84
|
res = ip.run_cell('tmp=1;"""a\nb"""\n')
|
|
85
|
self.assertEqual(ip.user_ns['tmp'], 1)
|
|
85
|
self.assertEqual(ip.user_ns['tmp'], 1)
|
|
86
|
self.assertEqual(res.success, True)
|
|
86
|
self.assertEqual(res.success, True)
|
|
87
|
self.assertEqual(res.result, "a\nb")
|
|
87
|
self.assertEqual(res.result, "a\nb")
|
|
88
|
|
|
88
|
|
|
89
|
def test_dont_cache_with_semicolon(self):
|
|
89
|
def test_dont_cache_with_semicolon(self):
|
|
90
|
"Ending a line with semicolon should not cache the returned object (GH-307)"
|
|
90
|
"Ending a line with semicolon should not cache the returned object (GH-307)"
|
|
91
|
oldlen = len(ip.user_ns['Out'])
|
|
91
|
oldlen = len(ip.user_ns['Out'])
|
|
92
|
for cell in ['1;', '1;1;']:
|
|
92
|
for cell in ['1;', '1;1;']:
|
|
93
|
res = ip.run_cell(cell, store_history=True)
|
|
93
|
res = ip.run_cell(cell, store_history=True)
|
|
94
|
newlen = len(ip.user_ns['Out'])
|
|
94
|
newlen = len(ip.user_ns['Out'])
|
|
95
|
self.assertEqual(oldlen, newlen)
|
|
95
|
self.assertEqual(oldlen, newlen)
|
|
96
|
self.assertIsNone(res.result)
|
|
96
|
self.assertIsNone(res.result)
|
|
97
|
i = 0
|
|
97
|
i = 0
|
|
98
|
#also test the default caching behavior
|
|
98
|
#also test the default caching behavior
|
|
99
|
for cell in ['1', '1;1']:
|
|
99
|
for cell in ['1', '1;1']:
|
|
100
|
ip.run_cell(cell, store_history=True)
|
|
100
|
ip.run_cell(cell, store_history=True)
|
|
101
|
newlen = len(ip.user_ns['Out'])
|
|
101
|
newlen = len(ip.user_ns['Out'])
|
|
102
|
i += 1
|
|
102
|
i += 1
|
|
103
|
self.assertEqual(oldlen+i, newlen)
|
|
103
|
self.assertEqual(oldlen+i, newlen)
|
|
104
|
|
|
104
|
|
|
105
|
def test_syntax_error(self):
|
|
105
|
def test_syntax_error(self):
|
|
106
|
res = ip.run_cell("raise = 3")
|
|
106
|
res = ip.run_cell("raise = 3")
|
|
107
|
self.assertIsInstance(res.error_before_exec, SyntaxError)
|
|
107
|
self.assertIsInstance(res.error_before_exec, SyntaxError)
|
|
108
|
|
|
108
|
|
|
109
|
def test_In_variable(self):
|
|
109
|
def test_In_variable(self):
|
|
110
|
"Verify that In variable grows with user input (GH-284)"
|
|
110
|
"Verify that In variable grows with user input (GH-284)"
|
|
111
|
oldlen = len(ip.user_ns['In'])
|
|
111
|
oldlen = len(ip.user_ns['In'])
|
|
112
|
ip.run_cell('1;', store_history=True)
|
|
112
|
ip.run_cell('1;', store_history=True)
|
|
113
|
newlen = len(ip.user_ns['In'])
|
|
113
|
newlen = len(ip.user_ns['In'])
|
|
114
|
self.assertEqual(oldlen+1, newlen)
|
|
114
|
self.assertEqual(oldlen+1, newlen)
|
|
115
|
self.assertEqual(ip.user_ns['In'][-1],'1;')
|
|
115
|
self.assertEqual(ip.user_ns['In'][-1],'1;')
|
|
116
|
|
|
116
|
|
|
117
|
def test_magic_names_in_string(self):
|
|
117
|
def test_magic_names_in_string(self):
|
|
118
|
ip.run_cell('a = """\n%exit\n"""')
|
|
118
|
ip.run_cell('a = """\n%exit\n"""')
|
|
119
|
self.assertEqual(ip.user_ns['a'], '\n%exit\n')
|
|
119
|
self.assertEqual(ip.user_ns['a'], '\n%exit\n')
|
|
120
|
|
|
120
|
|
|
121
|
def test_trailing_newline(self):
|
|
121
|
def test_trailing_newline(self):
|
|
122
|
"""test that running !(command) does not raise a SyntaxError"""
|
|
122
|
"""test that running !(command) does not raise a SyntaxError"""
|
|
123
|
ip.run_cell('!(true)\n', False)
|
|
123
|
ip.run_cell('!(true)\n', False)
|
|
124
|
ip.run_cell('!(true)\n\n\n', False)
|
|
124
|
ip.run_cell('!(true)\n\n\n', False)
|
|
125
|
|
|
125
|
|
|
126
|
def test_gh_597(self):
|
|
126
|
def test_gh_597(self):
|
|
127
|
"""Pretty-printing lists of objects with non-ascii reprs may cause
|
|
127
|
"""Pretty-printing lists of objects with non-ascii reprs may cause
|
|
128
|
problems."""
|
|
128
|
problems."""
|
|
129
|
class Spam(object):
|
|
129
|
class Spam(object):
|
|
130
|
def __repr__(self):
|
|
130
|
def __repr__(self):
|
|
131
|
return "\xe9"*50
|
|
131
|
return "\xe9"*50
|
|
132
|
import IPython.core.formatters
|
|
132
|
import IPython.core.formatters
|
|
133
|
f = IPython.core.formatters.PlainTextFormatter()
|
|
133
|
f = IPython.core.formatters.PlainTextFormatter()
|
|
134
|
f([Spam(),Spam()])
|
|
134
|
f([Spam(),Spam()])
|
|
135
|
|
|
135
|
|
|
136
|
|
|
136
|
|
|
137
|
def test_future_flags(self):
|
|
137
|
def test_future_flags(self):
|
|
138
|
"""Check that future flags are used for parsing code (gh-777)"""
|
|
138
|
"""Check that future flags are used for parsing code (gh-777)"""
|
|
139
|
ip.run_cell('from __future__ import barry_as_FLUFL')
|
|
139
|
ip.run_cell('from __future__ import barry_as_FLUFL')
|
|
140
|
try:
|
|
140
|
try:
|
|
141
|
ip.run_cell('prfunc_return_val = 1 <> 2')
|
|
141
|
ip.run_cell('prfunc_return_val = 1 <> 2')
|
|
142
|
assert 'prfunc_return_val' in ip.user_ns
|
|
142
|
assert 'prfunc_return_val' in ip.user_ns
|
|
143
|
finally:
|
|
143
|
finally:
|
|
144
|
# Reset compiler flags so we don't mess up other tests.
|
|
144
|
# Reset compiler flags so we don't mess up other tests.
|
|
145
|
ip.compile.reset_compiler_flags()
|
|
145
|
ip.compile.reset_compiler_flags()
|
|
146
|
|
|
146
|
|
|
147
|
def test_can_pickle(self):
|
|
147
|
def test_can_pickle(self):
|
|
148
|
"Can we pickle objects defined interactively (GH-29)"
|
|
148
|
"Can we pickle objects defined interactively (GH-29)"
|
|
149
|
ip = get_ipython()
|
|
149
|
ip = get_ipython()
|
|
150
|
ip.reset()
|
|
150
|
ip.reset()
|
|
151
|
ip.run_cell(("class Mylist(list):\n"
|
|
151
|
ip.run_cell(("class Mylist(list):\n"
|
|
152
|
" def __init__(self,x=[]):\n"
|
|
152
|
" def __init__(self,x=[]):\n"
|
|
153
|
" list.__init__(self,x)"))
|
|
153
|
" list.__init__(self,x)"))
|
|
154
|
ip.run_cell("w=Mylist([1,2,3])")
|
|
154
|
ip.run_cell("w=Mylist([1,2,3])")
|
|
155
|
|
|
155
|
|
|
156
|
from pickle import dumps
|
|
156
|
from pickle import dumps
|
|
157
|
|
|
157
|
|
|
158
|
# We need to swap in our main module - this is only necessary
|
|
158
|
# We need to swap in our main module - this is only necessary
|
|
159
|
# inside the test framework, because IPython puts the interactive module
|
|
159
|
# inside the test framework, because IPython puts the interactive module
|
|
160
|
# in place (but the test framework undoes this).
|
|
160
|
# in place (but the test framework undoes this).
|
|
161
|
_main = sys.modules['__main__']
|
|
161
|
_main = sys.modules['__main__']
|
|
162
|
sys.modules['__main__'] = ip.user_module
|
|
162
|
sys.modules['__main__'] = ip.user_module
|
|
163
|
try:
|
|
163
|
try:
|
|
164
|
res = dumps(ip.user_ns["w"])
|
|
164
|
res = dumps(ip.user_ns["w"])
|
|
165
|
finally:
|
|
165
|
finally:
|
|
166
|
sys.modules['__main__'] = _main
|
|
166
|
sys.modules['__main__'] = _main
|
|
167
|
self.assertTrue(isinstance(res, bytes))
|
|
167
|
self.assertTrue(isinstance(res, bytes))
|
|
168
|
|
|
168
|
|
|
169
|
def test_global_ns(self):
|
|
169
|
def test_global_ns(self):
|
|
170
|
"Code in functions must be able to access variables outside them."
|
|
170
|
"Code in functions must be able to access variables outside them."
|
|
171
|
ip = get_ipython()
|
|
171
|
ip = get_ipython()
|
|
172
|
ip.run_cell("a = 10")
|
|
172
|
ip.run_cell("a = 10")
|
|
173
|
ip.run_cell(("def f(x):\n"
|
|
173
|
ip.run_cell(("def f(x):\n"
|
|
174
|
" return x + a"))
|
|
174
|
" return x + a"))
|
|
175
|
ip.run_cell("b = f(12)")
|
|
175
|
ip.run_cell("b = f(12)")
|
|
176
|
self.assertEqual(ip.user_ns["b"], 22)
|
|
176
|
self.assertEqual(ip.user_ns["b"], 22)
|
|
177
|
|
|
177
|
|
|
178
|
def test_bad_custom_tb(self):
|
|
178
|
def test_bad_custom_tb(self):
|
|
179
|
"""Check that InteractiveShell is protected from bad custom exception handlers"""
|
|
179
|
"""Check that InteractiveShell is protected from bad custom exception handlers"""
|
|
180
|
ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
|
|
180
|
ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
|
|
181
|
self.assertEqual(ip.custom_exceptions, (IOError,))
|
|
181
|
self.assertEqual(ip.custom_exceptions, (IOError,))
|
|
182
|
with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
|
|
182
|
with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
|
|
183
|
ip.run_cell(u'raise IOError("foo")')
|
|
183
|
ip.run_cell(u'raise IOError("foo")')
|
|
184
|
self.assertEqual(ip.custom_exceptions, ())
|
|
184
|
self.assertEqual(ip.custom_exceptions, ())
|
|
185
|
|
|
185
|
|
|
186
|
def test_bad_custom_tb_return(self):
|
|
186
|
def test_bad_custom_tb_return(self):
|
|
187
|
"""Check that InteractiveShell is protected from bad return types in custom exception handlers"""
|
|
187
|
"""Check that InteractiveShell is protected from bad return types in custom exception handlers"""
|
|
188
|
ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
|
|
188
|
ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
|
|
189
|
self.assertEqual(ip.custom_exceptions, (NameError,))
|
|
189
|
self.assertEqual(ip.custom_exceptions, (NameError,))
|
|
190
|
with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
|
|
190
|
with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
|
|
191
|
ip.run_cell(u'a=abracadabra')
|
|
191
|
ip.run_cell(u'a=abracadabra')
|
|
192
|
self.assertEqual(ip.custom_exceptions, ())
|
|
192
|
self.assertEqual(ip.custom_exceptions, ())
|
|
193
|
|
|
193
|
|
|
194
|
def test_drop_by_id(self):
|
|
194
|
def test_drop_by_id(self):
|
|
195
|
myvars = {"a":object(), "b":object(), "c": object()}
|
|
195
|
myvars = {"a":object(), "b":object(), "c": object()}
|
|
196
|
ip.push(myvars, interactive=False)
|
|
196
|
ip.push(myvars, interactive=False)
|
|
197
|
for name in myvars:
|
|
197
|
for name in myvars:
|
|
198
|
assert name in ip.user_ns, name
|
|
198
|
assert name in ip.user_ns, name
|
|
199
|
assert name in ip.user_ns_hidden, name
|
|
199
|
assert name in ip.user_ns_hidden, name
|
|
200
|
ip.user_ns['b'] = 12
|
|
200
|
ip.user_ns['b'] = 12
|
|
201
|
ip.drop_by_id(myvars)
|
|
201
|
ip.drop_by_id(myvars)
|
|
202
|
for name in ["a", "c"]:
|
|
202
|
for name in ["a", "c"]:
|
|
203
|
assert name not in ip.user_ns, name
|
|
203
|
assert name not in ip.user_ns, name
|
|
204
|
assert name not in ip.user_ns_hidden, name
|
|
204
|
assert name not in ip.user_ns_hidden, name
|
|
205
|
assert ip.user_ns['b'] == 12
|
|
205
|
assert ip.user_ns['b'] == 12
|
|
206
|
ip.reset()
|
|
206
|
ip.reset()
|
|
207
|
|
|
207
|
|
|
208
|
def test_var_expand(self):
|
|
208
|
def test_var_expand(self):
|
|
209
|
ip.user_ns['f'] = u'Ca\xf1o'
|
|
209
|
ip.user_ns['f'] = u'Ca\xf1o'
|
|
210
|
self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
|
|
210
|
self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
|
|
211
|
self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
|
|
211
|
self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
|
|
212
|
self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
|
|
212
|
self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
|
|
213
|
self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
|
|
213
|
self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
|
|
214
|
|
|
214
|
|
|
215
|
self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
|
|
215
|
self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
|
|
216
|
|
|
216
|
|
|
217
|
ip.user_ns['f'] = b'Ca\xc3\xb1o'
|
|
217
|
ip.user_ns['f'] = b'Ca\xc3\xb1o'
|
|
218
|
# This should not raise any exception:
|
|
218
|
# This should not raise any exception:
|
|
219
|
ip.var_expand(u'echo $f')
|
|
219
|
ip.var_expand(u'echo $f')
|
|
220
|
|
|
220
|
|
|
221
|
def test_var_expand_local(self):
|
|
221
|
def test_var_expand_local(self):
|
|
222
|
"""Test local variable expansion in !system and %magic calls"""
|
|
222
|
"""Test local variable expansion in !system and %magic calls"""
|
|
223
|
# !system
|
|
223
|
# !system
|
|
224
|
ip.run_cell('def test():\n'
|
|
224
|
ip.run_cell('def test():\n'
|
|
225
|
' lvar = "ttt"\n'
|
|
225
|
' lvar = "ttt"\n'
|
|
226
|
' ret = !echo {lvar}\n'
|
|
226
|
' ret = !echo {lvar}\n'
|
|
227
|
' return ret[0]\n')
|
|
227
|
' return ret[0]\n')
|
|
228
|
res = ip.user_ns['test']()
|
|
228
|
res = ip.user_ns['test']()
|
|
229
|
nt.assert_in('ttt', res)
|
|
229
|
nt.assert_in('ttt', res)
|
|
230
|
|
|
230
|
|
|
231
|
# %magic
|
|
231
|
# %magic
|
|
232
|
ip.run_cell('def makemacro():\n'
|
|
232
|
ip.run_cell('def makemacro():\n'
|
|
233
|
' macroname = "macro_var_expand_locals"\n'
|
|
233
|
' macroname = "macro_var_expand_locals"\n'
|
|
234
|
' %macro {macroname} codestr\n')
|
|
234
|
' %macro {macroname} codestr\n')
|
|
235
|
ip.user_ns['codestr'] = "str(12)"
|
|
235
|
ip.user_ns['codestr'] = "str(12)"
|
|
236
|
ip.run_cell('makemacro()')
|
|
236
|
ip.run_cell('makemacro()')
|
|
237
|
nt.assert_in('macro_var_expand_locals', ip.user_ns)
|
|
237
|
nt.assert_in('macro_var_expand_locals', ip.user_ns)
|
|
238
|
|
|
238
|
|
|
239
|
def test_var_expand_self(self):
|
|
239
|
def test_var_expand_self(self):
|
|
240
|
"""Test variable expansion with the name 'self', which was failing.
|
|
240
|
"""Test variable expansion with the name 'self', which was failing.
|
|
241
|
|
|
241
|
|
|
242
|
See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
|
|
242
|
See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
|
|
243
|
"""
|
|
243
|
"""
|
|
244
|
ip.run_cell('class cTest:\n'
|
|
244
|
ip.run_cell('class cTest:\n'
|
|
245
|
' classvar="see me"\n'
|
|
245
|
' classvar="see me"\n'
|
|
246
|
' def test(self):\n'
|
|
246
|
' def test(self):\n'
|
|
247
|
' res = !echo Variable: {self.classvar}\n'
|
|
247
|
' res = !echo Variable: {self.classvar}\n'
|
|
248
|
' return res[0]\n')
|
|
248
|
' return res[0]\n')
|
|
249
|
nt.assert_in('see me', ip.user_ns['cTest']().test())
|
|
249
|
nt.assert_in('see me', ip.user_ns['cTest']().test())
|
|
250
|
|
|
250
|
|
|
251
|
def test_bad_var_expand(self):
|
|
251
|
def test_bad_var_expand(self):
|
|
252
|
"""var_expand on invalid formats shouldn't raise"""
|
|
252
|
"""var_expand on invalid formats shouldn't raise"""
|
|
253
|
# SyntaxError
|
|
253
|
# SyntaxError
|
|
254
|
self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
|
|
254
|
self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
|
|
255
|
# NameError
|
|
255
|
# NameError
|
|
256
|
self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
|
|
256
|
self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
|
|
257
|
# ZeroDivisionError
|
|
257
|
# ZeroDivisionError
|
|
258
|
self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
|
|
258
|
self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
|
|
259
|
|
|
259
|
|
|
260
|
def test_silent_postexec(self):
|
|
260
|
def test_silent_postexec(self):
|
|
261
|
"""run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
|
|
261
|
"""run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
|
|
262
|
pre_explicit = mock.Mock()
|
|
262
|
pre_explicit = mock.Mock()
|
|
263
|
pre_always = mock.Mock()
|
|
263
|
pre_always = mock.Mock()
|
|
264
|
post_explicit = mock.Mock()
|
|
264
|
post_explicit = mock.Mock()
|
|
265
|
post_always = mock.Mock()
|
|
265
|
post_always = mock.Mock()
|
|
|
|
|
266
|
finally_explicit = mock.Mock()
|
|
|
|
|
267
|
finally_always = mock.Mock()
|
|
|
|
|
268
|
all_mocks = [pre_explicit, pre_always, post_explicit, post_always,
|
|
|
|
|
269
|
finally_explicit,finally_always]
|
|
266
|
|
|
270
|
|
|
267
|
ip.events.register('pre_run_cell', pre_explicit)
|
|
271
|
ip.events.register('pre_run_cell', pre_explicit)
|
|
268
|
ip.events.register('pre_execute', pre_always)
|
|
272
|
ip.events.register('pre_execute', pre_always)
|
|
269
|
ip.events.register('post_run_cell', post_explicit)
|
|
273
|
ip.events.register('post_run_cell', post_explicit)
|
|
270
|
ip.events.register('post_execute', post_always)
|
|
274
|
ip.events.register('post_execute', post_always)
|
|
|
|
|
275
|
ip.events.register('finally_run_cell', finally_explicit)
|
|
|
|
|
276
|
ip.events.register('finally_execute', finally_always)
|
|
271
|
|
|
277
|
|
|
272
|
try:
|
|
278
|
try:
|
|
273
|
ip.run_cell("1", silent=True)
|
|
279
|
ip.run_cell("1", silent=True)
|
|
274
|
assert pre_always.called
|
|
280
|
assert pre_always.called
|
|
275
|
assert not pre_explicit.called
|
|
281
|
assert not pre_explicit.called
|
|
276
|
assert post_always.called
|
|
282
|
assert post_always.called
|
|
277
|
assert not post_explicit.called
|
|
283
|
assert not post_explicit.called
|
|
|
|
|
284
|
assert finally_always.called
|
|
|
|
|
285
|
assert not finally_explicit.called
|
|
278
|
# double-check that non-silent exec did what we expected
|
|
286
|
# double-check that non-silent exec did what we expected
|
|
279
|
# silent to avoid
|
|
287
|
# silent to avoid
|
|
280
|
ip.run_cell("1")
|
|
288
|
ip.run_cell("1")
|
|
281
|
assert pre_explicit.called
|
|
289
|
assert pre_explicit.called
|
|
282
|
assert post_explicit.called
|
|
290
|
assert post_explicit.called
|
|
|
|
|
291
|
assert finally_explicit.called
|
|
|
|
|
292
|
# check that finally hooks are always called
|
|
|
|
|
293
|
[m.reset_mock() for m in all_mocks]
|
|
|
|
|
294
|
ip.run_cell("syntax error")
|
|
|
|
|
295
|
assert pre_always.called
|
|
|
|
|
296
|
assert pre_explicit.called
|
|
|
|
|
297
|
assert not post_always.called # because of `SyntaxError`
|
|
|
|
|
298
|
assert not post_explicit.called
|
|
|
|
|
299
|
assert finally_explicit.called
|
|
|
|
|
300
|
assert finally_always.called
|
|
283
|
finally:
|
|
301
|
finally:
|
|
284
|
# remove post-exec
|
|
302
|
# remove post-exec
|
|
285
|
ip.events.unregister('pre_run_cell', pre_explicit)
|
|
303
|
ip.events.unregister('pre_run_cell', pre_explicit)
|
|
286
|
ip.events.unregister('pre_execute', pre_always)
|
|
304
|
ip.events.unregister('pre_execute', pre_always)
|
|
287
|
ip.events.unregister('post_run_cell', post_explicit)
|
|
305
|
ip.events.unregister('post_run_cell', post_explicit)
|
|
288
|
ip.events.unregister('post_execute', post_always)
|
|
306
|
ip.events.unregister('post_execute', post_always)
|
|
|
|
|
307
|
ip.events.unregister('finally_run_cell', finally_explicit)
|
|
|
|
|
308
|
ip.events.unregister('finally_execute', finally_always)
|
|
289
|
|
|
309
|
|
|
290
|
def test_silent_noadvance(self):
|
|
310
|
def test_silent_noadvance(self):
|
|
291
|
"""run_cell(silent=True) doesn't advance execution_count"""
|
|
311
|
"""run_cell(silent=True) doesn't advance execution_count"""
|
|
292
|
ec = ip.execution_count
|
|
312
|
ec = ip.execution_count
|
|
293
|
# silent should force store_history=False
|
|
313
|
# silent should force store_history=False
|
|
294
|
ip.run_cell("1", store_history=True, silent=True)
|
|
314
|
ip.run_cell("1", store_history=True, silent=True)
|
|
295
|
|
|
315
|
|
|
296
|
self.assertEqual(ec, ip.execution_count)
|
|
316
|
self.assertEqual(ec, ip.execution_count)
|
|
297
|
# double-check that non-silent exec did what we expected
|
|
317
|
# double-check that non-silent exec did what we expected
|
|
298
|
# silent to avoid
|
|
318
|
# silent to avoid
|
|
299
|
ip.run_cell("1", store_history=True)
|
|
319
|
ip.run_cell("1", store_history=True)
|
|
300
|
self.assertEqual(ec+1, ip.execution_count)
|
|
320
|
self.assertEqual(ec+1, ip.execution_count)
|
|
301
|
|
|
321
|
|
|
302
|
def test_silent_nodisplayhook(self):
|
|
322
|
def test_silent_nodisplayhook(self):
|
|
303
|
"""run_cell(silent=True) doesn't trigger displayhook"""
|
|
323
|
"""run_cell(silent=True) doesn't trigger displayhook"""
|
|
304
|
d = dict(called=False)
|
|
324
|
d = dict(called=False)
|
|
305
|
|
|
325
|
|
|
306
|
trap = ip.display_trap
|
|
326
|
trap = ip.display_trap
|
|
307
|
save_hook = trap.hook
|
|
327
|
save_hook = trap.hook
|
|
308
|
|
|
328
|
|
|
309
|
def failing_hook(*args, **kwargs):
|
|
329
|
def failing_hook(*args, **kwargs):
|
|
310
|
d['called'] = True
|
|
330
|
d['called'] = True
|
|
311
|
|
|
331
|
|
|
312
|
try:
|
|
332
|
try:
|
|
313
|
trap.hook = failing_hook
|
|
333
|
trap.hook = failing_hook
|
|
314
|
res = ip.run_cell("1", silent=True)
|
|
334
|
res = ip.run_cell("1", silent=True)
|
|
315
|
self.assertFalse(d['called'])
|
|
335
|
self.assertFalse(d['called'])
|
|
316
|
self.assertIsNone(res.result)
|
|
336
|
self.assertIsNone(res.result)
|
|
317
|
# double-check that non-silent exec did what we expected
|
|
337
|
# double-check that non-silent exec did what we expected
|
|
318
|
# silent to avoid
|
|
338
|
# silent to avoid
|
|
319
|
ip.run_cell("1")
|
|
339
|
ip.run_cell("1")
|
|
320
|
self.assertTrue(d['called'])
|
|
340
|
self.assertTrue(d['called'])
|
|
321
|
finally:
|
|
341
|
finally:
|
|
322
|
trap.hook = save_hook
|
|
342
|
trap.hook = save_hook
|
|
323
|
|
|
343
|
|
|
324
|
def test_ofind_line_magic(self):
|
|
344
|
def test_ofind_line_magic(self):
|
|
325
|
from IPython.core.magic import register_line_magic
|
|
345
|
from IPython.core.magic import register_line_magic
|
|
326
|
|
|
346
|
|
|
327
|
@register_line_magic
|
|
347
|
@register_line_magic
|
|
328
|
def lmagic(line):
|
|
348
|
def lmagic(line):
|
|
329
|
"A line magic"
|
|
349
|
"A line magic"
|
|
330
|
|
|
350
|
|
|
331
|
# Get info on line magic
|
|
351
|
# Get info on line magic
|
|
332
|
lfind = ip._ofind('lmagic')
|
|
352
|
lfind = ip._ofind('lmagic')
|
|
333
|
info = dict(found=True, isalias=False, ismagic=True,
|
|
353
|
info = dict(found=True, isalias=False, ismagic=True,
|
|
334
|
namespace = 'IPython internal', obj= lmagic.__wrapped__,
|
|
354
|
namespace = 'IPython internal', obj= lmagic.__wrapped__,
|
|
335
|
parent = None)
|
|
355
|
parent = None)
|
|
336
|
nt.assert_equal(lfind, info)
|
|
356
|
nt.assert_equal(lfind, info)
|
|
337
|
|
|
357
|
|
|
338
|
def test_ofind_cell_magic(self):
|
|
358
|
def test_ofind_cell_magic(self):
|
|
339
|
from IPython.core.magic import register_cell_magic
|
|
359
|
from IPython.core.magic import register_cell_magic
|
|
340
|
|
|
360
|
|
|
341
|
@register_cell_magic
|
|
361
|
@register_cell_magic
|
|
342
|
def cmagic(line, cell):
|
|
362
|
def cmagic(line, cell):
|
|
343
|
"A cell magic"
|
|
363
|
"A cell magic"
|
|
344
|
|
|
364
|
|
|
345
|
# Get info on cell magic
|
|
365
|
# Get info on cell magic
|
|
346
|
find = ip._ofind('cmagic')
|
|
366
|
find = ip._ofind('cmagic')
|
|
347
|
info = dict(found=True, isalias=False, ismagic=True,
|
|
367
|
info = dict(found=True, isalias=False, ismagic=True,
|
|
348
|
namespace = 'IPython internal', obj= cmagic.__wrapped__,
|
|
368
|
namespace = 'IPython internal', obj= cmagic.__wrapped__,
|
|
349
|
parent = None)
|
|
369
|
parent = None)
|
|
350
|
nt.assert_equal(find, info)
|
|
370
|
nt.assert_equal(find, info)
|
|
351
|
|
|
371
|
|
|
352
|
def test_ofind_property_with_error(self):
|
|
372
|
def test_ofind_property_with_error(self):
|
|
353
|
class A(object):
|
|
373
|
class A(object):
|
|
354
|
@property
|
|
374
|
@property
|
|
355
|
def foo(self):
|
|
375
|
def foo(self):
|
|
356
|
raise NotImplementedError()
|
|
376
|
raise NotImplementedError()
|
|
357
|
a = A()
|
|
377
|
a = A()
|
|
358
|
|
|
378
|
|
|
359
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
379
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
360
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
380
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
361
|
namespace='locals', obj=A.foo, parent=a)
|
|
381
|
namespace='locals', obj=A.foo, parent=a)
|
|
362
|
nt.assert_equal(found, info)
|
|
382
|
nt.assert_equal(found, info)
|
|
363
|
|
|
383
|
|
|
364
|
def test_ofind_multiple_attribute_lookups(self):
|
|
384
|
def test_ofind_multiple_attribute_lookups(self):
|
|
365
|
class A(object):
|
|
385
|
class A(object):
|
|
366
|
@property
|
|
386
|
@property
|
|
367
|
def foo(self):
|
|
387
|
def foo(self):
|
|
368
|
raise NotImplementedError()
|
|
388
|
raise NotImplementedError()
|
|
369
|
|
|
389
|
|
|
370
|
a = A()
|
|
390
|
a = A()
|
|
371
|
a.a = A()
|
|
391
|
a.a = A()
|
|
372
|
a.a.a = A()
|
|
392
|
a.a.a = A()
|
|
373
|
|
|
393
|
|
|
374
|
found = ip._ofind('a.a.a.foo', [('locals', locals())])
|
|
394
|
found = ip._ofind('a.a.a.foo', [('locals', locals())])
|
|
375
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
395
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
376
|
namespace='locals', obj=A.foo, parent=a.a.a)
|
|
396
|
namespace='locals', obj=A.foo, parent=a.a.a)
|
|
377
|
nt.assert_equal(found, info)
|
|
397
|
nt.assert_equal(found, info)
|
|
378
|
|
|
398
|
|
|
379
|
def test_ofind_slotted_attributes(self):
|
|
399
|
def test_ofind_slotted_attributes(self):
|
|
380
|
class A(object):
|
|
400
|
class A(object):
|
|
381
|
__slots__ = ['foo']
|
|
401
|
__slots__ = ['foo']
|
|
382
|
def __init__(self):
|
|
402
|
def __init__(self):
|
|
383
|
self.foo = 'bar'
|
|
403
|
self.foo = 'bar'
|
|
384
|
|
|
404
|
|
|
385
|
a = A()
|
|
405
|
a = A()
|
|
386
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
406
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
387
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
407
|
info = dict(found=True, isalias=False, ismagic=False,
|
|
388
|
namespace='locals', obj=a.foo, parent=a)
|
|
408
|
namespace='locals', obj=a.foo, parent=a)
|
|
389
|
nt.assert_equal(found, info)
|
|
409
|
nt.assert_equal(found, info)
|
|
390
|
|
|
410
|
|
|
391
|
found = ip._ofind('a.bar', [('locals', locals())])
|
|
411
|
found = ip._ofind('a.bar', [('locals', locals())])
|
|
392
|
info = dict(found=False, isalias=False, ismagic=False,
|
|
412
|
info = dict(found=False, isalias=False, ismagic=False,
|
|
393
|
namespace=None, obj=None, parent=a)
|
|
413
|
namespace=None, obj=None, parent=a)
|
|
394
|
nt.assert_equal(found, info)
|
|
414
|
nt.assert_equal(found, info)
|
|
395
|
|
|
415
|
|
|
396
|
def test_ofind_prefers_property_to_instance_level_attribute(self):
|
|
416
|
def test_ofind_prefers_property_to_instance_level_attribute(self):
|
|
397
|
class A(object):
|
|
417
|
class A(object):
|
|
398
|
@property
|
|
418
|
@property
|
|
399
|
def foo(self):
|
|
419
|
def foo(self):
|
|
400
|
return 'bar'
|
|
420
|
return 'bar'
|
|
401
|
a = A()
|
|
421
|
a = A()
|
|
402
|
a.__dict__['foo'] = 'baz'
|
|
422
|
a.__dict__['foo'] = 'baz'
|
|
403
|
nt.assert_equal(a.foo, 'bar')
|
|
423
|
nt.assert_equal(a.foo, 'bar')
|
|
404
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
424
|
found = ip._ofind('a.foo', [('locals', locals())])
|
|
405
|
nt.assert_is(found['obj'], A.foo)
|
|
425
|
nt.assert_is(found['obj'], A.foo)
|
|
406
|
|
|
426
|
|
|
407
|
def test_custom_syntaxerror_exception(self):
|
|
427
|
def test_custom_syntaxerror_exception(self):
|
|
408
|
called = []
|
|
428
|
called = []
|
|
409
|
def my_handler(shell, etype, value, tb, tb_offset=None):
|
|
429
|
def my_handler(shell, etype, value, tb, tb_offset=None):
|
|
410
|
called.append(etype)
|
|
430
|
called.append(etype)
|
|
411
|
shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
|
|
431
|
shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
|
|
412
|
|
|
432
|
|
|
413
|
ip.set_custom_exc((SyntaxError,), my_handler)
|
|
433
|
ip.set_custom_exc((SyntaxError,), my_handler)
|
|
414
|
try:
|
|
434
|
try:
|
|
415
|
ip.run_cell("1f")
|
|
435
|
ip.run_cell("1f")
|
|
416
|
# Check that this was called, and only once.
|
|
436
|
# Check that this was called, and only once.
|
|
417
|
self.assertEqual(called, [SyntaxError])
|
|
437
|
self.assertEqual(called, [SyntaxError])
|
|
418
|
finally:
|
|
438
|
finally:
|
|
419
|
# Reset the custom exception hook
|
|
439
|
# Reset the custom exception hook
|
|
420
|
ip.set_custom_exc((), None)
|
|
440
|
ip.set_custom_exc((), None)
|
|
421
|
|
|
441
|
|
|
422
|
def test_custom_exception(self):
|
|
442
|
def test_custom_exception(self):
|
|
423
|
called = []
|
|
443
|
called = []
|
|
424
|
def my_handler(shell, etype, value, tb, tb_offset=None):
|
|
444
|
def my_handler(shell, etype, value, tb, tb_offset=None):
|
|
425
|
called.append(etype)
|
|
445
|
called.append(etype)
|
|
426
|
shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
|
|
446
|
shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
|
|
427
|
|
|
447
|
|
|
428
|
ip.set_custom_exc((ValueError,), my_handler)
|
|
448
|
ip.set_custom_exc((ValueError,), my_handler)
|
|
429
|
try:
|
|
449
|
try:
|
|
430
|
res = ip.run_cell("raise ValueError('test')")
|
|
450
|
res = ip.run_cell("raise ValueError('test')")
|
|
431
|
# Check that this was called, and only once.
|
|
451
|
# Check that this was called, and only once.
|
|
432
|
self.assertEqual(called, [ValueError])
|
|
452
|
self.assertEqual(called, [ValueError])
|
|
433
|
# Check that the error is on the result object
|
|
453
|
# Check that the error is on the result object
|
|
434
|
self.assertIsInstance(res.error_in_exec, ValueError)
|
|
454
|
self.assertIsInstance(res.error_in_exec, ValueError)
|
|
435
|
finally:
|
|
455
|
finally:
|
|
436
|
# Reset the custom exception hook
|
|
456
|
# Reset the custom exception hook
|
|
437
|
ip.set_custom_exc((), None)
|
|
457
|
ip.set_custom_exc((), None)
|
|
438
|
|
|
458
|
|
|
439
|
def test_mktempfile(self):
|
|
459
|
def test_mktempfile(self):
|
|
440
|
filename = ip.mktempfile()
|
|
460
|
filename = ip.mktempfile()
|
|
441
|
# Check that we can open the file again on Windows
|
|
461
|
# Check that we can open the file again on Windows
|
|
442
|
with open(filename, 'w') as f:
|
|
462
|
with open(filename, 'w') as f:
|
|
443
|
f.write('abc')
|
|
463
|
f.write('abc')
|
|
444
|
|
|
464
|
|
|
445
|
filename = ip.mktempfile(data='blah')
|
|
465
|
filename = ip.mktempfile(data='blah')
|
|
446
|
with open(filename, 'r') as f:
|
|
466
|
with open(filename, 'r') as f:
|
|
447
|
self.assertEqual(f.read(), 'blah')
|
|
467
|
self.assertEqual(f.read(), 'blah')
|
|
448
|
|
|
468
|
|
|
449
|
def test_new_main_mod(self):
|
|
469
|
def test_new_main_mod(self):
|
|
450
|
# Smoketest to check that this accepts a unicode module name
|
|
470
|
# Smoketest to check that this accepts a unicode module name
|
|
451
|
name = u'jiefmw'
|
|
471
|
name = u'jiefmw'
|
|
452
|
mod = ip.new_main_mod(u'%s.py' % name, name)
|
|
472
|
mod = ip.new_main_mod(u'%s.py' % name, name)
|
|
453
|
self.assertEqual(mod.__name__, name)
|
|
473
|
self.assertEqual(mod.__name__, name)
|
|
454
|
|
|
474
|
|
|
455
|
def test_get_exception_only(self):
|
|
475
|
def test_get_exception_only(self):
|
|
456
|
try:
|
|
476
|
try:
|
|
457
|
raise KeyboardInterrupt
|
|
477
|
raise KeyboardInterrupt
|
|
458
|
except KeyboardInterrupt:
|
|
478
|
except KeyboardInterrupt:
|
|
459
|
msg = ip.get_exception_only()
|
|
479
|
msg = ip.get_exception_only()
|
|
460
|
self.assertEqual(msg, 'KeyboardInterrupt\n')
|
|
480
|
self.assertEqual(msg, 'KeyboardInterrupt\n')
|
|
461
|
|
|
481
|
|
|
462
|
try:
|
|
482
|
try:
|
|
463
|
raise DerivedInterrupt("foo")
|
|
483
|
raise DerivedInterrupt("foo")
|
|
464
|
except KeyboardInterrupt:
|
|
484
|
except KeyboardInterrupt:
|
|
465
|
msg = ip.get_exception_only()
|
|
485
|
msg = ip.get_exception_only()
|
|
466
|
self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
|
|
486
|
self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
|
|
467
|
|
|
487
|
|
|
468
|
def test_inspect_text(self):
|
|
488
|
def test_inspect_text(self):
|
|
469
|
ip.run_cell('a = 5')
|
|
489
|
ip.run_cell('a = 5')
|
|
470
|
text = ip.object_inspect_text('a')
|
|
490
|
text = ip.object_inspect_text('a')
|
|
471
|
self.assertIsInstance(text, str)
|
|
491
|
self.assertIsInstance(text, str)
|
|
472
|
|
|
492
|
|
|
473
|
def test_last_execution_result(self):
|
|
493
|
def test_last_execution_result(self):
|
|
474
|
""" Check that last execution result gets set correctly (GH-10702) """
|
|
494
|
""" Check that last execution result gets set correctly (GH-10702) """
|
|
475
|
result = ip.run_cell('a = 5; a')
|
|
495
|
result = ip.run_cell('a = 5; a')
|
|
476
|
self.assertTrue(ip.last_execution_succeeded)
|
|
496
|
self.assertTrue(ip.last_execution_succeeded)
|
|
477
|
self.assertEqual(ip.last_execution_result.result, 5)
|
|
497
|
self.assertEqual(ip.last_execution_result.result, 5)
|
|
478
|
|
|
498
|
|
|
479
|
result = ip.run_cell('a = x_invalid_id_x')
|
|
499
|
result = ip.run_cell('a = x_invalid_id_x')
|
|
480
|
self.assertFalse(ip.last_execution_succeeded)
|
|
500
|
self.assertFalse(ip.last_execution_succeeded)
|
|
481
|
self.assertFalse(ip.last_execution_result.success)
|
|
501
|
self.assertFalse(ip.last_execution_result.success)
|
|
482
|
self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
|
|
502
|
self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
|
|
483
|
|
|
503
|
|
|
484
|
|
|
504
|
|
|
485
|
class TestSafeExecfileNonAsciiPath(unittest.TestCase):
|
|
505
|
class TestSafeExecfileNonAsciiPath(unittest.TestCase):
|
|
486
|
|
|
506
|
|
|
487
|
@onlyif_unicode_paths
|
|
507
|
@onlyif_unicode_paths
|
|
488
|
def setUp(self):
|
|
508
|
def setUp(self):
|
|
489
|
self.BASETESTDIR = tempfile.mkdtemp()
|
|
509
|
self.BASETESTDIR = tempfile.mkdtemp()
|
|
490
|
self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
|
|
510
|
self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
|
|
491
|
os.mkdir(self.TESTDIR)
|
|
511
|
os.mkdir(self.TESTDIR)
|
|
492
|
with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
|
|
512
|
with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
|
|
493
|
sfile.write("pass\n")
|
|
513
|
sfile.write("pass\n")
|
|
494
|
self.oldpath = os.getcwd()
|
|
514
|
self.oldpath = os.getcwd()
|
|
495
|
os.chdir(self.TESTDIR)
|
|
515
|
os.chdir(self.TESTDIR)
|
|
496
|
self.fname = u"Γ₯Àâtestscript.py"
|
|
516
|
self.fname = u"Γ₯Àâtestscript.py"
|
|
497
|
|
|
517
|
|
|
498
|
def tearDown(self):
|
|
518
|
def tearDown(self):
|
|
499
|
os.chdir(self.oldpath)
|
|
519
|
os.chdir(self.oldpath)
|
|
500
|
shutil.rmtree(self.BASETESTDIR)
|
|
520
|
shutil.rmtree(self.BASETESTDIR)
|
|
501
|
|
|
521
|
|
|
502
|
@onlyif_unicode_paths
|
|
522
|
@onlyif_unicode_paths
|
|
503
|
def test_1(self):
|
|
523
|
def test_1(self):
|
|
504
|
"""Test safe_execfile with non-ascii path
|
|
524
|
"""Test safe_execfile with non-ascii path
|
|
505
|
"""
|
|
525
|
"""
|
|
506
|
ip.safe_execfile(self.fname, {}, raise_exceptions=True)
|
|
526
|
ip.safe_execfile(self.fname, {}, raise_exceptions=True)
|
|
507
|
|
|
527
|
|
|
508
|
class ExitCodeChecks(tt.TempFileMixin):
|
|
528
|
class ExitCodeChecks(tt.TempFileMixin):
|
|
509
|
def test_exit_code_ok(self):
|
|
529
|
def test_exit_code_ok(self):
|
|
510
|
self.system('exit 0')
|
|
530
|
self.system('exit 0')
|
|
511
|
self.assertEqual(ip.user_ns['_exit_code'], 0)
|
|
531
|
self.assertEqual(ip.user_ns['_exit_code'], 0)
|
|
512
|
|
|
532
|
|
|
513
|
def test_exit_code_error(self):
|
|
533
|
def test_exit_code_error(self):
|
|
514
|
self.system('exit 1')
|
|
534
|
self.system('exit 1')
|
|
515
|
self.assertEqual(ip.user_ns['_exit_code'], 1)
|
|
535
|
self.assertEqual(ip.user_ns['_exit_code'], 1)
|
|
516
|
|
|
536
|
|
|
517
|
@skipif(not hasattr(signal, 'SIGALRM'))
|
|
537
|
@skipif(not hasattr(signal, 'SIGALRM'))
|
|
518
|
def test_exit_code_signal(self):
|
|
538
|
def test_exit_code_signal(self):
|
|
519
|
self.mktmp("import signal, time\n"
|
|
539
|
self.mktmp("import signal, time\n"
|
|
520
|
"signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
|
|
540
|
"signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
|
|
521
|
"time.sleep(1)\n")
|
|
541
|
"time.sleep(1)\n")
|
|
522
|
self.system("%s %s" % (sys.executable, self.fname))
|
|
542
|
self.system("%s %s" % (sys.executable, self.fname))
|
|
523
|
self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
|
|
543
|
self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
|
|
524
|
|
|
544
|
|
|
525
|
@onlyif_cmds_exist("csh")
|
|
545
|
@onlyif_cmds_exist("csh")
|
|
526
|
def test_exit_code_signal_csh(self):
|
|
546
|
def test_exit_code_signal_csh(self):
|
|
527
|
SHELL = os.environ.get('SHELL', None)
|
|
547
|
SHELL = os.environ.get('SHELL', None)
|
|
528
|
os.environ['SHELL'] = find_cmd("csh")
|
|
548
|
os.environ['SHELL'] = find_cmd("csh")
|
|
529
|
try:
|
|
549
|
try:
|
|
530
|
self.test_exit_code_signal()
|
|
550
|
self.test_exit_code_signal()
|
|
531
|
finally:
|
|
551
|
finally:
|
|
532
|
if SHELL is not None:
|
|
552
|
if SHELL is not None:
|
|
533
|
os.environ['SHELL'] = SHELL
|
|
553
|
os.environ['SHELL'] = SHELL
|
|
534
|
else:
|
|
554
|
else:
|
|
535
|
del os.environ['SHELL']
|
|
555
|
del os.environ['SHELL']
|
|
536
|
|
|
556
|
|
|
537
|
class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
|
|
557
|
class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
|
|
538
|
system = ip.system_raw
|
|
558
|
system = ip.system_raw
|
|
539
|
|
|
559
|
|
|
540
|
@onlyif_unicode_paths
|
|
560
|
@onlyif_unicode_paths
|
|
541
|
def test_1(self):
|
|
561
|
def test_1(self):
|
|
542
|
"""Test system_raw with non-ascii cmd
|
|
562
|
"""Test system_raw with non-ascii cmd
|
|
543
|
"""
|
|
563
|
"""
|
|
544
|
cmd = u'''python -c "'Γ₯Àâ'" '''
|
|
564
|
cmd = u'''python -c "'Γ₯Àâ'" '''
|
|
545
|
ip.system_raw(cmd)
|
|
565
|
ip.system_raw(cmd)
|
|
546
|
|
|
566
|
|
|
547
|
@mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
|
|
567
|
@mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
|
|
548
|
@mock.patch('os.system', side_effect=KeyboardInterrupt)
|
|
568
|
@mock.patch('os.system', side_effect=KeyboardInterrupt)
|
|
549
|
def test_control_c(self, *mocks):
|
|
569
|
def test_control_c(self, *mocks):
|
|
550
|
try:
|
|
570
|
try:
|
|
551
|
self.system("sleep 1 # wont happen")
|
|
571
|
self.system("sleep 1 # wont happen")
|
|
552
|
except KeyboardInterrupt:
|
|
572
|
except KeyboardInterrupt:
|
|
553
|
self.fail("system call should intercept "
|
|
573
|
self.fail("system call should intercept "
|
|
554
|
"keyboard interrupt from subprocess.call")
|
|
574
|
"keyboard interrupt from subprocess.call")
|
|
555
|
self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
|
|
575
|
self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
|
|
556
|
|
|
576
|
|
|
557
|
# TODO: Exit codes are currently ignored on Windows.
|
|
577
|
# TODO: Exit codes are currently ignored on Windows.
|
|
558
|
class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
|
|
578
|
class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
|
|
559
|
system = ip.system_piped
|
|
579
|
system = ip.system_piped
|
|
560
|
|
|
580
|
|
|
561
|
@skip_win32
|
|
581
|
@skip_win32
|
|
562
|
def test_exit_code_ok(self):
|
|
582
|
def test_exit_code_ok(self):
|
|
563
|
ExitCodeChecks.test_exit_code_ok(self)
|
|
583
|
ExitCodeChecks.test_exit_code_ok(self)
|
|
564
|
|
|
584
|
|
|
565
|
@skip_win32
|
|
585
|
@skip_win32
|
|
566
|
def test_exit_code_error(self):
|
|
586
|
def test_exit_code_error(self):
|
|
567
|
ExitCodeChecks.test_exit_code_error(self)
|
|
587
|
ExitCodeChecks.test_exit_code_error(self)
|
|
568
|
|
|
588
|
|
|
569
|
@skip_win32
|
|
589
|
@skip_win32
|
|
570
|
def test_exit_code_signal(self):
|
|
590
|
def test_exit_code_signal(self):
|
|
571
|
ExitCodeChecks.test_exit_code_signal(self)
|
|
591
|
ExitCodeChecks.test_exit_code_signal(self)
|
|
572
|
|
|
592
|
|
|
573
|
class TestModules(unittest.TestCase, tt.TempFileMixin):
|
|
593
|
class TestModules(unittest.TestCase, tt.TempFileMixin):
|
|
574
|
def test_extraneous_loads(self):
|
|
594
|
def test_extraneous_loads(self):
|
|
575
|
"""Test we're not loading modules on startup that we shouldn't.
|
|
595
|
"""Test we're not loading modules on startup that we shouldn't.
|
|
576
|
"""
|
|
596
|
"""
|
|
577
|
self.mktmp("import sys\n"
|
|
597
|
self.mktmp("import sys\n"
|
|
578
|
"print('numpy' in sys.modules)\n"
|
|
598
|
"print('numpy' in sys.modules)\n"
|
|
579
|
"print('ipyparallel' in sys.modules)\n"
|
|
599
|
"print('ipyparallel' in sys.modules)\n"
|
|
580
|
"print('ipykernel' in sys.modules)\n"
|
|
600
|
"print('ipykernel' in sys.modules)\n"
|
|
581
|
)
|
|
601
|
)
|
|
582
|
out = "False\nFalse\nFalse\n"
|
|
602
|
out = "False\nFalse\nFalse\n"
|
|
583
|
tt.ipexec_validate(self.fname, out)
|
|
603
|
tt.ipexec_validate(self.fname, out)
|
|
584
|
|
|
604
|
|
|
585
|
class Negator(ast.NodeTransformer):
|
|
605
|
class Negator(ast.NodeTransformer):
|
|
586
|
"""Negates all number literals in an AST."""
|
|
606
|
"""Negates all number literals in an AST."""
|
|
587
|
def visit_Num(self, node):
|
|
607
|
def visit_Num(self, node):
|
|
588
|
node.n = -node.n
|
|
608
|
node.n = -node.n
|
|
589
|
return node
|
|
609
|
return node
|
|
590
|
|
|
610
|
|
|
591
|
class TestAstTransform(unittest.TestCase):
|
|
611
|
class TestAstTransform(unittest.TestCase):
|
|
592
|
def setUp(self):
|
|
612
|
def setUp(self):
|
|
593
|
self.negator = Negator()
|
|
613
|
self.negator = Negator()
|
|
594
|
ip.ast_transformers.append(self.negator)
|
|
614
|
ip.ast_transformers.append(self.negator)
|
|
595
|
|
|
615
|
|
|
596
|
def tearDown(self):
|
|
616
|
def tearDown(self):
|
|
597
|
ip.ast_transformers.remove(self.negator)
|
|
617
|
ip.ast_transformers.remove(self.negator)
|
|
598
|
|
|
618
|
|
|
599
|
def test_run_cell(self):
|
|
619
|
def test_run_cell(self):
|
|
600
|
with tt.AssertPrints('-34'):
|
|
620
|
with tt.AssertPrints('-34'):
|
|
601
|
ip.run_cell('print (12 + 22)')
|
|
621
|
ip.run_cell('print (12 + 22)')
|
|
602
|
|
|
622
|
|
|
603
|
# A named reference to a number shouldn't be transformed.
|
|
623
|
# A named reference to a number shouldn't be transformed.
|
|
604
|
ip.user_ns['n'] = 55
|
|
624
|
ip.user_ns['n'] = 55
|
|
605
|
with tt.AssertNotPrints('-55'):
|
|
625
|
with tt.AssertNotPrints('-55'):
|
|
606
|
ip.run_cell('print (n)')
|
|
626
|
ip.run_cell('print (n)')
|
|
607
|
|
|
627
|
|
|
608
|
def test_timeit(self):
|
|
628
|
def test_timeit(self):
|
|
609
|
called = set()
|
|
629
|
called = set()
|
|
610
|
def f(x):
|
|
630
|
def f(x):
|
|
611
|
called.add(x)
|
|
631
|
called.add(x)
|
|
612
|
ip.push({'f':f})
|
|
632
|
ip.push({'f':f})
|
|
613
|
|
|
633
|
|
|
614
|
with tt.AssertPrints("std. dev. of"):
|
|
634
|
with tt.AssertPrints("std. dev. of"):
|
|
615
|
ip.run_line_magic("timeit", "-n1 f(1)")
|
|
635
|
ip.run_line_magic("timeit", "-n1 f(1)")
|
|
616
|
self.assertEqual(called, {-1})
|
|
636
|
self.assertEqual(called, {-1})
|
|
617
|
called.clear()
|
|
637
|
called.clear()
|
|
618
|
|
|
638
|
|
|
619
|
with tt.AssertPrints("std. dev. of"):
|
|
639
|
with tt.AssertPrints("std. dev. of"):
|
|
620
|
ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
|
|
640
|
ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
|
|
621
|
self.assertEqual(called, {-2, -3})
|
|
641
|
self.assertEqual(called, {-2, -3})
|
|
622
|
|
|
642
|
|
|
623
|
def test_time(self):
|
|
643
|
def test_time(self):
|
|
624
|
called = []
|
|
644
|
called = []
|
|
625
|
def f(x):
|
|
645
|
def f(x):
|
|
626
|
called.append(x)
|
|
646
|
called.append(x)
|
|
627
|
ip.push({'f':f})
|
|
647
|
ip.push({'f':f})
|
|
628
|
|
|
648
|
|
|
629
|
# Test with an expression
|
|
649
|
# Test with an expression
|
|
630
|
with tt.AssertPrints("Wall time: "):
|
|
650
|
with tt.AssertPrints("Wall time: "):
|
|
631
|
ip.run_line_magic("time", "f(5+9)")
|
|
651
|
ip.run_line_magic("time", "f(5+9)")
|
|
632
|
self.assertEqual(called, [-14])
|
|
652
|
self.assertEqual(called, [-14])
|
|
633
|
called[:] = []
|
|
653
|
called[:] = []
|
|
634
|
|
|
654
|
|
|
635
|
# Test with a statement (different code path)
|
|
655
|
# Test with a statement (different code path)
|
|
636
|
with tt.AssertPrints("Wall time: "):
|
|
656
|
with tt.AssertPrints("Wall time: "):
|
|
637
|
ip.run_line_magic("time", "a = f(-3 + -2)")
|
|
657
|
ip.run_line_magic("time", "a = f(-3 + -2)")
|
|
638
|
self.assertEqual(called, [5])
|
|
658
|
self.assertEqual(called, [5])
|
|
639
|
|
|
659
|
|
|
640
|
def test_macro(self):
|
|
660
|
def test_macro(self):
|
|
641
|
ip.push({'a':10})
|
|
661
|
ip.push({'a':10})
|
|
642
|
# The AST transformation makes this do a+=-1
|
|
662
|
# The AST transformation makes this do a+=-1
|
|
643
|
ip.define_macro("amacro", "a+=1\nprint(a)")
|
|
663
|
ip.define_macro("amacro", "a+=1\nprint(a)")
|
|
644
|
|
|
664
|
|
|
645
|
with tt.AssertPrints("9"):
|
|
665
|
with tt.AssertPrints("9"):
|
|
646
|
ip.run_cell("amacro")
|
|
666
|
ip.run_cell("amacro")
|
|
647
|
with tt.AssertPrints("8"):
|
|
667
|
with tt.AssertPrints("8"):
|
|
648
|
ip.run_cell("amacro")
|
|
668
|
ip.run_cell("amacro")
|
|
649
|
|
|
669
|
|
|
650
|
class IntegerWrapper(ast.NodeTransformer):
|
|
670
|
class IntegerWrapper(ast.NodeTransformer):
|
|
651
|
"""Wraps all integers in a call to Integer()"""
|
|
671
|
"""Wraps all integers in a call to Integer()"""
|
|
652
|
def visit_Num(self, node):
|
|
672
|
def visit_Num(self, node):
|
|
653
|
if isinstance(node.n, int):
|
|
673
|
if isinstance(node.n, int):
|
|
654
|
return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
|
|
674
|
return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
|
|
655
|
args=[node], keywords=[])
|
|
675
|
args=[node], keywords=[])
|
|
656
|
return node
|
|
676
|
return node
|
|
657
|
|
|
677
|
|
|
658
|
class TestAstTransform2(unittest.TestCase):
|
|
678
|
class TestAstTransform2(unittest.TestCase):
|
|
659
|
def setUp(self):
|
|
679
|
def setUp(self):
|
|
660
|
self.intwrapper = IntegerWrapper()
|
|
680
|
self.intwrapper = IntegerWrapper()
|
|
661
|
ip.ast_transformers.append(self.intwrapper)
|
|
681
|
ip.ast_transformers.append(self.intwrapper)
|
|
662
|
|
|
682
|
|
|
663
|
self.calls = []
|
|
683
|
self.calls = []
|
|
664
|
def Integer(*args):
|
|
684
|
def Integer(*args):
|
|
665
|
self.calls.append(args)
|
|
685
|
self.calls.append(args)
|
|
666
|
return args
|
|
686
|
return args
|
|
667
|
ip.push({"Integer": Integer})
|
|
687
|
ip.push({"Integer": Integer})
|
|
668
|
|
|
688
|
|
|
669
|
def tearDown(self):
|
|
689
|
def tearDown(self):
|
|
670
|
ip.ast_transformers.remove(self.intwrapper)
|
|
690
|
ip.ast_transformers.remove(self.intwrapper)
|
|
671
|
del ip.user_ns['Integer']
|
|
691
|
del ip.user_ns['Integer']
|
|
672
|
|
|
692
|
|
|
673
|
def test_run_cell(self):
|
|
693
|
def test_run_cell(self):
|
|
674
|
ip.run_cell("n = 2")
|
|
694
|
ip.run_cell("n = 2")
|
|
675
|
self.assertEqual(self.calls, [(2,)])
|
|
695
|
self.assertEqual(self.calls, [(2,)])
|
|
676
|
|
|
696
|
|
|
677
|
# This shouldn't throw an error
|
|
697
|
# This shouldn't throw an error
|
|
678
|
ip.run_cell("o = 2.0")
|
|
698
|
ip.run_cell("o = 2.0")
|
|
679
|
self.assertEqual(ip.user_ns['o'], 2.0)
|
|
699
|
self.assertEqual(ip.user_ns['o'], 2.0)
|
|
680
|
|
|
700
|
|
|
681
|
def test_timeit(self):
|
|
701
|
def test_timeit(self):
|
|
682
|
called = set()
|
|
702
|
called = set()
|
|
683
|
def f(x):
|
|
703
|
def f(x):
|
|
684
|
called.add(x)
|
|
704
|
called.add(x)
|
|
685
|
ip.push({'f':f})
|
|
705
|
ip.push({'f':f})
|
|
686
|
|
|
706
|
|
|
687
|
with tt.AssertPrints("std. dev. of"):
|
|
707
|
with tt.AssertPrints("std. dev. of"):
|
|
688
|
ip.run_line_magic("timeit", "-n1 f(1)")
|
|
708
|
ip.run_line_magic("timeit", "-n1 f(1)")
|
|
689
|
self.assertEqual(called, {(1,)})
|
|
709
|
self.assertEqual(called, {(1,)})
|
|
690
|
called.clear()
|
|
710
|
called.clear()
|
|
691
|
|
|
711
|
|
|
692
|
with tt.AssertPrints("std. dev. of"):
|
|
712
|
with tt.AssertPrints("std. dev. of"):
|
|
693
|
ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
|
|
713
|
ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
|
|
694
|
self.assertEqual(called, {(2,), (3,)})
|
|
714
|
self.assertEqual(called, {(2,), (3,)})
|
|
695
|
|
|
715
|
|
|
696
|
class ErrorTransformer(ast.NodeTransformer):
|
|
716
|
class ErrorTransformer(ast.NodeTransformer):
|
|
697
|
"""Throws an error when it sees a number."""
|
|
717
|
"""Throws an error when it sees a number."""
|
|
698
|
def visit_Num(self, node):
|
|
718
|
def visit_Num(self, node):
|
|
699
|
raise ValueError("test")
|
|
719
|
raise ValueError("test")
|
|
700
|
|
|
720
|
|
|
701
|
class TestAstTransformError(unittest.TestCase):
|
|
721
|
class TestAstTransformError(unittest.TestCase):
|
|
702
|
def test_unregistering(self):
|
|
722
|
def test_unregistering(self):
|
|
703
|
err_transformer = ErrorTransformer()
|
|
723
|
err_transformer = ErrorTransformer()
|
|
704
|
ip.ast_transformers.append(err_transformer)
|
|
724
|
ip.ast_transformers.append(err_transformer)
|
|
705
|
|
|
725
|
|
|
706
|
with tt.AssertPrints("unregister", channel='stderr'):
|
|
726
|
with tt.AssertPrints("unregister", channel='stderr'):
|
|
707
|
ip.run_cell("1 + 2")
|
|
727
|
ip.run_cell("1 + 2")
|
|
708
|
|
|
728
|
|
|
709
|
# This should have been removed.
|
|
729
|
# This should have been removed.
|
|
710
|
nt.assert_not_in(err_transformer, ip.ast_transformers)
|
|
730
|
nt.assert_not_in(err_transformer, ip.ast_transformers)
|
|
711
|
|
|
731
|
|
|
712
|
|
|
732
|
|
|
713
|
class StringRejector(ast.NodeTransformer):
|
|
733
|
class StringRejector(ast.NodeTransformer):
|
|
714
|
"""Throws an InputRejected when it sees a string literal.
|
|
734
|
"""Throws an InputRejected when it sees a string literal.
|
|
715
|
|
|
735
|
|
|
716
|
Used to verify that NodeTransformers can signal that a piece of code should
|
|
736
|
Used to verify that NodeTransformers can signal that a piece of code should
|
|
717
|
not be executed by throwing an InputRejected.
|
|
737
|
not be executed by throwing an InputRejected.
|
|
718
|
"""
|
|
738
|
"""
|
|
719
|
|
|
739
|
|
|
720
|
def visit_Str(self, node):
|
|
740
|
def visit_Str(self, node):
|
|
721
|
raise InputRejected("test")
|
|
741
|
raise InputRejected("test")
|
|
722
|
|
|
742
|
|
|
723
|
|
|
743
|
|
|
724
|
class TestAstTransformInputRejection(unittest.TestCase):
|
|
744
|
class TestAstTransformInputRejection(unittest.TestCase):
|
|
725
|
|
|
745
|
|
|
726
|
def setUp(self):
|
|
746
|
def setUp(self):
|
|
727
|
self.transformer = StringRejector()
|
|
747
|
self.transformer = StringRejector()
|
|
728
|
ip.ast_transformers.append(self.transformer)
|
|
748
|
ip.ast_transformers.append(self.transformer)
|
|
729
|
|
|
749
|
|
|
730
|
def tearDown(self):
|
|
750
|
def tearDown(self):
|
|
731
|
ip.ast_transformers.remove(self.transformer)
|
|
751
|
ip.ast_transformers.remove(self.transformer)
|
|
732
|
|
|
752
|
|
|
733
|
def test_input_rejection(self):
|
|
753
|
def test_input_rejection(self):
|
|
734
|
"""Check that NodeTransformers can reject input."""
|
|
754
|
"""Check that NodeTransformers can reject input."""
|
|
735
|
|
|
755
|
|
|
736
|
expect_exception_tb = tt.AssertPrints("InputRejected: test")
|
|
756
|
expect_exception_tb = tt.AssertPrints("InputRejected: test")
|
|
737
|
expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
|
|
757
|
expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
|
|
738
|
|
|
758
|
|
|
739
|
# Run the same check twice to verify that the transformer is not
|
|
759
|
# Run the same check twice to verify that the transformer is not
|
|
740
|
# disabled after raising.
|
|
760
|
# disabled after raising.
|
|
741
|
with expect_exception_tb, expect_no_cell_output:
|
|
761
|
with expect_exception_tb, expect_no_cell_output:
|
|
742
|
ip.run_cell("'unsafe'")
|
|
762
|
ip.run_cell("'unsafe'")
|
|
743
|
|
|
763
|
|
|
744
|
with expect_exception_tb, expect_no_cell_output:
|
|
764
|
with expect_exception_tb, expect_no_cell_output:
|
|
745
|
res = ip.run_cell("'unsafe'")
|
|
765
|
res = ip.run_cell("'unsafe'")
|
|
746
|
|
|
766
|
|
|
747
|
self.assertIsInstance(res.error_before_exec, InputRejected)
|
|
767
|
self.assertIsInstance(res.error_before_exec, InputRejected)
|
|
748
|
|
|
768
|
|
|
749
|
def test__IPYTHON__():
|
|
769
|
def test__IPYTHON__():
|
|
750
|
# This shouldn't raise a NameError, that's all
|
|
770
|
# This shouldn't raise a NameError, that's all
|
|
751
|
__IPYTHON__
|
|
771
|
__IPYTHON__
|
|
752
|
|
|
772
|
|
|
753
|
|
|
773
|
|
|
754
|
class DummyRepr(object):
|
|
774
|
class DummyRepr(object):
|
|
755
|
def __repr__(self):
|
|
775
|
def __repr__(self):
|
|
756
|
return "DummyRepr"
|
|
776
|
return "DummyRepr"
|
|
757
|
|
|
777
|
|
|
758
|
def _repr_html_(self):
|
|
778
|
def _repr_html_(self):
|
|
759
|
return "<b>dummy</b>"
|
|
779
|
return "<b>dummy</b>"
|
|
760
|
|
|
780
|
|
|
761
|
def _repr_javascript_(self):
|
|
781
|
def _repr_javascript_(self):
|
|
762
|
return "console.log('hi');", {'key': 'value'}
|
|
782
|
return "console.log('hi');", {'key': 'value'}
|
|
763
|
|
|
783
|
|
|
764
|
|
|
784
|
|
|
765
|
def test_user_variables():
|
|
785
|
def test_user_variables():
|
|
766
|
# enable all formatters
|
|
786
|
# enable all formatters
|
|
767
|
ip.display_formatter.active_types = ip.display_formatter.format_types
|
|
787
|
ip.display_formatter.active_types = ip.display_formatter.format_types
|
|
768
|
|
|
788
|
|
|
769
|
ip.user_ns['dummy'] = d = DummyRepr()
|
|
789
|
ip.user_ns['dummy'] = d = DummyRepr()
|
|
770
|
keys = {'dummy', 'doesnotexist'}
|
|
790
|
keys = {'dummy', 'doesnotexist'}
|
|
771
|
r = ip.user_expressions({ key:key for key in keys})
|
|
791
|
r = ip.user_expressions({ key:key for key in keys})
|
|
772
|
|
|
792
|
|
|
773
|
nt.assert_equal(keys, set(r.keys()))
|
|
793
|
nt.assert_equal(keys, set(r.keys()))
|
|
774
|
dummy = r['dummy']
|
|
794
|
dummy = r['dummy']
|
|
775
|
nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
|
|
795
|
nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
|
|
776
|
nt.assert_equal(dummy['status'], 'ok')
|
|
796
|
nt.assert_equal(dummy['status'], 'ok')
|
|
777
|
data = dummy['data']
|
|
797
|
data = dummy['data']
|
|
778
|
metadata = dummy['metadata']
|
|
798
|
metadata = dummy['metadata']
|
|
779
|
nt.assert_equal(data.get('text/html'), d._repr_html_())
|
|
799
|
nt.assert_equal(data.get('text/html'), d._repr_html_())
|
|
780
|
js, jsmd = d._repr_javascript_()
|
|
800
|
js, jsmd = d._repr_javascript_()
|
|
781
|
nt.assert_equal(data.get('application/javascript'), js)
|
|
801
|
nt.assert_equal(data.get('application/javascript'), js)
|
|
782
|
nt.assert_equal(metadata.get('application/javascript'), jsmd)
|
|
802
|
nt.assert_equal(metadata.get('application/javascript'), jsmd)
|
|
783
|
|
|
803
|
|
|
784
|
dne = r['doesnotexist']
|
|
804
|
dne = r['doesnotexist']
|
|
785
|
nt.assert_equal(dne['status'], 'error')
|
|
805
|
nt.assert_equal(dne['status'], 'error')
|
|
786
|
nt.assert_equal(dne['ename'], 'NameError')
|
|
806
|
nt.assert_equal(dne['ename'], 'NameError')
|
|
787
|
|
|
807
|
|
|
788
|
# back to text only
|
|
808
|
# back to text only
|
|
789
|
ip.display_formatter.active_types = ['text/plain']
|
|
809
|
ip.display_formatter.active_types = ['text/plain']
|
|
790
|
|
|
810
|
|
|
791
|
def test_user_expression():
|
|
811
|
def test_user_expression():
|
|
792
|
# enable all formatters
|
|
812
|
# enable all formatters
|
|
793
|
ip.display_formatter.active_types = ip.display_formatter.format_types
|
|
813
|
ip.display_formatter.active_types = ip.display_formatter.format_types
|
|
794
|
query = {
|
|
814
|
query = {
|
|
795
|
'a' : '1 + 2',
|
|
815
|
'a' : '1 + 2',
|
|
796
|
'b' : '1/0',
|
|
816
|
'b' : '1/0',
|
|
797
|
}
|
|
817
|
}
|
|
798
|
r = ip.user_expressions(query)
|
|
818
|
r = ip.user_expressions(query)
|
|
799
|
import pprint
|
|
819
|
import pprint
|
|
800
|
pprint.pprint(r)
|
|
820
|
pprint.pprint(r)
|
|
801
|
nt.assert_equal(set(r.keys()), set(query.keys()))
|
|
821
|
nt.assert_equal(set(r.keys()), set(query.keys()))
|
|
802
|
a = r['a']
|
|
822
|
a = r['a']
|
|
803
|
nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
|
|
823
|
nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
|
|
804
|
nt.assert_equal(a['status'], 'ok')
|
|
824
|
nt.assert_equal(a['status'], 'ok')
|
|
805
|
data = a['data']
|
|
825
|
data = a['data']
|
|
806
|
metadata = a['metadata']
|
|
826
|
metadata = a['metadata']
|
|
807
|
nt.assert_equal(data.get('text/plain'), '3')
|
|
827
|
nt.assert_equal(data.get('text/plain'), '3')
|
|
808
|
|
|
828
|
|
|
809
|
b = r['b']
|
|
829
|
b = r['b']
|
|
810
|
nt.assert_equal(b['status'], 'error')
|
|
830
|
nt.assert_equal(b['status'], 'error')
|
|
811
|
nt.assert_equal(b['ename'], 'ZeroDivisionError')
|
|
831
|
nt.assert_equal(b['ename'], 'ZeroDivisionError')
|
|
812
|
|
|
832
|
|
|
813
|
# back to text only
|
|
833
|
# back to text only
|
|
814
|
ip.display_formatter.active_types = ['text/plain']
|
|
834
|
ip.display_formatter.active_types = ['text/plain']
|
|
815
|
|
|
835
|
|
|
816
|
|
|
836
|
|
|
817
|
|
|
837
|
|
|
818
|
|
|
838
|
|
|
819
|
|
|
839
|
|
|
820
|
class TestSyntaxErrorTransformer(unittest.TestCase):
|
|
840
|
class TestSyntaxErrorTransformer(unittest.TestCase):
|
|
821
|
"""Check that SyntaxError raised by an input transformer is handled by run_cell()"""
|
|
841
|
"""Check that SyntaxError raised by an input transformer is handled by run_cell()"""
|
|
822
|
|
|
842
|
|
|
823
|
class SyntaxErrorTransformer(InputTransformer):
|
|
843
|
class SyntaxErrorTransformer(InputTransformer):
|
|
824
|
|
|
844
|
|
|
825
|
def push(self, line):
|
|
845
|
def push(self, line):
|
|
826
|
pos = line.find('syntaxerror')
|
|
846
|
pos = line.find('syntaxerror')
|
|
827
|
if pos >= 0:
|
|
847
|
if pos >= 0:
|
|
828
|
e = SyntaxError('input contains "syntaxerror"')
|
|
848
|
e = SyntaxError('input contains "syntaxerror"')
|
|
829
|
e.text = line
|
|
849
|
e.text = line
|
|
830
|
e.offset = pos + 1
|
|
850
|
e.offset = pos + 1
|
|
831
|
raise e
|
|
851
|
raise e
|
|
832
|
return line
|
|
852
|
return line
|
|
833
|
|
|
853
|
|
|
834
|
def reset(self):
|
|
854
|
def reset(self):
|
|
835
|
pass
|
|
855
|
pass
|
|
836
|
|
|
856
|
|
|
837
|
def setUp(self):
|
|
857
|
def setUp(self):
|
|
838
|
self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
|
|
858
|
self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
|
|
839
|
ip.input_splitter.python_line_transforms.append(self.transformer)
|
|
859
|
ip.input_splitter.python_line_transforms.append(self.transformer)
|
|
840
|
ip.input_transformer_manager.python_line_transforms.append(self.transformer)
|
|
860
|
ip.input_transformer_manager.python_line_transforms.append(self.transformer)
|
|
841
|
|
|
861
|
|
|
842
|
def tearDown(self):
|
|
862
|
def tearDown(self):
|
|
843
|
ip.input_splitter.python_line_transforms.remove(self.transformer)
|
|
863
|
ip.input_splitter.python_line_transforms.remove(self.transformer)
|
|
844
|
ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
|
|
864
|
ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
|
|
845
|
|
|
865
|
|
|
846
|
def test_syntaxerror_input_transformer(self):
|
|
866
|
def test_syntaxerror_input_transformer(self):
|
|
847
|
with tt.AssertPrints('1234'):
|
|
867
|
with tt.AssertPrints('1234'):
|
|
848
|
ip.run_cell('1234')
|
|
868
|
ip.run_cell('1234')
|
|
849
|
with tt.AssertPrints('SyntaxError: invalid syntax'):
|
|
869
|
with tt.AssertPrints('SyntaxError: invalid syntax'):
|
|
850
|
ip.run_cell('1 2 3') # plain python syntax error
|
|
870
|
ip.run_cell('1 2 3') # plain python syntax error
|
|
851
|
with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
|
|
871
|
with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
|
|
852
|
ip.run_cell('2345 # syntaxerror') # input transformer syntax error
|
|
872
|
ip.run_cell('2345 # syntaxerror') # input transformer syntax error
|
|
853
|
with tt.AssertPrints('3456'):
|
|
873
|
with tt.AssertPrints('3456'):
|
|
854
|
ip.run_cell('3456')
|
|
874
|
ip.run_cell('3456')
|
|
855
|
|
|
875
|
|
|
856
|
|
|
876
|
|
|
857
|
|
|
877
|
|
|
858
|
def test_warning_suppression():
|
|
878
|
def test_warning_suppression():
|
|
859
|
ip.run_cell("import warnings")
|
|
879
|
ip.run_cell("import warnings")
|
|
860
|
try:
|
|
880
|
try:
|
|
861
|
with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
|
|
881
|
with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
|
|
862
|
ip.run_cell("warnings.warn('asdf')")
|
|
882
|
ip.run_cell("warnings.warn('asdf')")
|
|
863
|
# Here's the real test -- if we run that again, we should get the
|
|
883
|
# Here's the real test -- if we run that again, we should get the
|
|
864
|
# warning again. Traditionally, each warning was only issued once per
|
|
884
|
# warning again. Traditionally, each warning was only issued once per
|
|
865
|
# IPython session (approximately), even if the user typed in new and
|
|
885
|
# IPython session (approximately), even if the user typed in new and
|
|
866
|
# different code that should have also triggered the warning, leading
|
|
886
|
# different code that should have also triggered the warning, leading
|
|
867
|
# to much confusion.
|
|
887
|
# to much confusion.
|
|
868
|
with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
|
|
888
|
with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
|
|
869
|
ip.run_cell("warnings.warn('asdf')")
|
|
889
|
ip.run_cell("warnings.warn('asdf')")
|
|
870
|
finally:
|
|
890
|
finally:
|
|
871
|
ip.run_cell("del warnings")
|
|
891
|
ip.run_cell("del warnings")
|
|
872
|
|
|
892
|
|
|
873
|
|
|
893
|
|
|
874
|
def test_deprecation_warning():
|
|
894
|
def test_deprecation_warning():
|
|
875
|
ip.run_cell("""
|
|
895
|
ip.run_cell("""
|
|
876
|
import warnings
|
|
896
|
import warnings
|
|
877
|
def wrn():
|
|
897
|
def wrn():
|
|
878
|
warnings.warn(
|
|
898
|
warnings.warn(
|
|
879
|
"I AM A WARNING",
|
|
899
|
"I AM A WARNING",
|
|
880
|
DeprecationWarning
|
|
900
|
DeprecationWarning
|
|
881
|
)
|
|
901
|
)
|
|
882
|
""")
|
|
902
|
""")
|
|
883
|
try:
|
|
903
|
try:
|
|
884
|
with tt.AssertPrints("I AM A WARNING", channel="stderr"):
|
|
904
|
with tt.AssertPrints("I AM A WARNING", channel="stderr"):
|
|
885
|
ip.run_cell("wrn()")
|
|
905
|
ip.run_cell("wrn()")
|
|
886
|
finally:
|
|
906
|
finally:
|
|
887
|
ip.run_cell("del warnings")
|
|
907
|
ip.run_cell("del warnings")
|
|
888
|
ip.run_cell("del wrn")
|
|
908
|
ip.run_cell("del wrn")
|
|
889
|
|
|
909
|
|
|
890
|
|
|
910
|
|
|
891
|
class TestImportNoDeprecate(tt.TempFileMixin):
|
|
911
|
class TestImportNoDeprecate(tt.TempFileMixin):
|
|
892
|
|
|
912
|
|
|
893
|
def setup(self):
|
|
913
|
def setup(self):
|
|
894
|
"""Make a valid python temp file."""
|
|
914
|
"""Make a valid python temp file."""
|
|
895
|
self.mktmp("""
|
|
915
|
self.mktmp("""
|
|
896
|
import warnings
|
|
916
|
import warnings
|
|
897
|
def wrn():
|
|
917
|
def wrn():
|
|
898
|
warnings.warn(
|
|
918
|
warnings.warn(
|
|
899
|
"I AM A WARNING",
|
|
919
|
"I AM A WARNING",
|
|
900
|
DeprecationWarning
|
|
920
|
DeprecationWarning
|
|
901
|
)
|
|
921
|
)
|
|
902
|
""")
|
|
922
|
""")
|
|
903
|
|
|
923
|
|
|
904
|
def test_no_dep(self):
|
|
924
|
def test_no_dep(self):
|
|
905
|
"""
|
|
925
|
"""
|
|
906
|
No deprecation warning should be raised from imported functions
|
|
926
|
No deprecation warning should be raised from imported functions
|
|
907
|
"""
|
|
927
|
"""
|
|
908
|
ip.run_cell("from {} import wrn".format(self.fname))
|
|
928
|
ip.run_cell("from {} import wrn".format(self.fname))
|
|
909
|
|
|
929
|
|
|
910
|
with tt.AssertNotPrints("I AM A WARNING"):
|
|
930
|
with tt.AssertNotPrints("I AM A WARNING"):
|
|
911
|
ip.run_cell("wrn()")
|
|
931
|
ip.run_cell("wrn()")
|
|
912
|
ip.run_cell("del wrn")
|
|
932
|
ip.run_cell("del wrn")
|