##// END OF EJS Templates
Verbose error message for syntax error occuring at runtime
Piotr Zielinski -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,347 +1,374 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.core.ultratb
3 3 """
4 4 import io
5 5 import sys
6 6 import os.path
7 7 from textwrap import dedent
8 8 import traceback
9 9 import unittest
10 10 from unittest import mock
11 11
12 12 from ..ultratb import ColorTB, VerboseTB, find_recursion
13 13
14 14
15 15 from IPython.testing import tools as tt
16 16 from IPython.testing.decorators import onlyif_unicode_paths
17 17 from IPython.utils.syspathcontext import prepended_to_syspath
18 18 from IPython.utils.tempdir import TemporaryDirectory
19 19
20 20 ip = get_ipython()
21 21
22 22 file_1 = """1
23 23 2
24 24 3
25 25 def f():
26 26 1/0
27 27 """
28 28
29 29 file_2 = """def f():
30 30 1/0
31 31 """
32 32
33 33 class ChangedPyFileTest(unittest.TestCase):
34 34 def test_changing_py_file(self):
35 35 """Traceback produced if the line where the error occurred is missing?
36 36
37 37 https://github.com/ipython/ipython/issues/1456
38 38 """
39 39 with TemporaryDirectory() as td:
40 40 fname = os.path.join(td, "foo.py")
41 41 with open(fname, "w") as f:
42 42 f.write(file_1)
43 43
44 44 with prepended_to_syspath(td):
45 45 ip.run_cell("import foo")
46 46
47 47 with tt.AssertPrints("ZeroDivisionError"):
48 48 ip.run_cell("foo.f()")
49 49
50 50 # Make the file shorter, so the line of the error is missing.
51 51 with open(fname, "w") as f:
52 52 f.write(file_2)
53 53
54 54 # For some reason, this was failing on the *second* call after
55 55 # changing the file, so we call f() twice.
56 56 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
57 57 with tt.AssertPrints("ZeroDivisionError"):
58 58 ip.run_cell("foo.f()")
59 59 with tt.AssertPrints("ZeroDivisionError"):
60 60 ip.run_cell("foo.f()")
61 61
62 62 iso_8859_5_file = u'''# coding: iso-8859-5
63 63
64 64 def fail():
65 65 """дбИЖ"""
66 66 1/0 # дбИЖ
67 67 '''
68 68
69 69 class NonAsciiTest(unittest.TestCase):
70 70 @onlyif_unicode_paths
71 71 def test_nonascii_path(self):
72 72 # Non-ascii directory name as well.
73 73 with TemporaryDirectory(suffix=u'é') as td:
74 74 fname = os.path.join(td, u"fooé.py")
75 75 with open(fname, "w") as f:
76 76 f.write(file_1)
77 77
78 78 with prepended_to_syspath(td):
79 79 ip.run_cell("import foo")
80 80
81 81 with tt.AssertPrints("ZeroDivisionError"):
82 82 ip.run_cell("foo.f()")
83 83
84 84 def test_iso8859_5(self):
85 85 with TemporaryDirectory() as td:
86 86 fname = os.path.join(td, 'dfghjkl.py')
87 87
88 88 with io.open(fname, 'w', encoding='iso-8859-5') as f:
89 89 f.write(iso_8859_5_file)
90 90
91 91 with prepended_to_syspath(td):
92 92 ip.run_cell("from dfghjkl import fail")
93 93
94 94 with tt.AssertPrints("ZeroDivisionError"):
95 95 with tt.AssertPrints(u'дбИЖ', suppress=False):
96 96 ip.run_cell('fail()')
97 97
98 98 def test_nonascii_msg(self):
99 99 cell = u"raise Exception('é')"
100 100 expected = u"Exception('é')"
101 101 ip.run_cell("%xmode plain")
102 102 with tt.AssertPrints(expected):
103 103 ip.run_cell(cell)
104 104
105 105 ip.run_cell("%xmode verbose")
106 106 with tt.AssertPrints(expected):
107 107 ip.run_cell(cell)
108 108
109 109 ip.run_cell("%xmode context")
110 110 with tt.AssertPrints(expected):
111 111 ip.run_cell(cell)
112 112
113 113
114 114 class NestedGenExprTestCase(unittest.TestCase):
115 115 """
116 116 Regression test for the following issues:
117 117 https://github.com/ipython/ipython/issues/8293
118 118 https://github.com/ipython/ipython/issues/8205
119 119 """
120 120 def test_nested_genexpr(self):
121 121 code = dedent(
122 122 """\
123 123 class SpecificException(Exception):
124 124 pass
125 125
126 126 def foo(x):
127 127 raise SpecificException("Success!")
128 128
129 129 sum(sum(foo(x) for _ in [0]) for x in [0])
130 130 """
131 131 )
132 132 with tt.AssertPrints('SpecificException: Success!', suppress=False):
133 133 ip.run_cell(code)
134 134
135 135
136 136 indentationerror_file = """if True:
137 137 zoon()
138 138 """
139 139
140 140 class IndentationErrorTest(unittest.TestCase):
141 141 def test_indentationerror_shows_line(self):
142 142 # See issue gh-2398
143 143 with tt.AssertPrints("IndentationError"):
144 144 with tt.AssertPrints("zoon()", suppress=False):
145 145 ip.run_cell(indentationerror_file)
146 146
147 147 with TemporaryDirectory() as td:
148 148 fname = os.path.join(td, "foo.py")
149 149 with open(fname, "w") as f:
150 150 f.write(indentationerror_file)
151 151
152 152 with tt.AssertPrints("IndentationError"):
153 153 with tt.AssertPrints("zoon()", suppress=False):
154 154 ip.magic('run %s' % fname)
155 155
156 156 se_file_1 = """1
157 157 2
158 158 7/
159 159 """
160 160
161 161 se_file_2 = """7/
162 162 """
163 163
164 164 class SyntaxErrorTest(unittest.TestCase):
165 165 def test_syntaxerror_without_lineno(self):
166 166 with tt.AssertNotPrints("TypeError"):
167 167 with tt.AssertPrints("line unknown"):
168 168 ip.run_cell("raise SyntaxError()")
169 169
170 def test_syntaxerror_no_stacktrace_at_compile_time(self):
171 syntax_error_at_compile_time = """
172 def foo():
173 ..
174 """
175 with tt.AssertPrints("SyntaxError"):
176 ip.run_cell(syntax_error_at_compile_time)
177
178 with tt.AssertNotPrints("foo()"):
179 ip.run_cell(syntax_error_at_compile_time)
180
181 def test_syntaxerror_stacktrace_when_running_compiled_code(self):
182 syntax_error_at_runtime = """
183 def foo():
184 eval("..")
185
186 def bar():
187 foo()
188
189 bar()
190 """
191 with tt.AssertPrints("SyntaxError"):
192 ip.run_cell(syntax_error_at_runtime)
193 # Assert syntax error during runtime generate stacktrace
194 with tt.AssertPrints(["foo()", "bar()"]):
195 ip.run_cell(syntax_error_at_runtime)
196
170 197 def test_changing_py_file(self):
171 198 with TemporaryDirectory() as td:
172 199 fname = os.path.join(td, "foo.py")
173 200 with open(fname, 'w') as f:
174 201 f.write(se_file_1)
175 202
176 203 with tt.AssertPrints(["7/", "SyntaxError"]):
177 204 ip.magic("run " + fname)
178 205
179 206 # Modify the file
180 207 with open(fname, 'w') as f:
181 208 f.write(se_file_2)
182 209
183 210 # The SyntaxError should point to the correct line
184 211 with tt.AssertPrints(["7/", "SyntaxError"]):
185 212 ip.magic("run " + fname)
186 213
187 214 def test_non_syntaxerror(self):
188 215 # SyntaxTB may be called with an error other than a SyntaxError
189 216 # See e.g. gh-4361
190 217 try:
191 218 raise ValueError('QWERTY')
192 219 except ValueError:
193 220 with tt.AssertPrints('QWERTY'):
194 221 ip.showsyntaxerror()
195 222
196 223
197 224 class Python3ChainedExceptionsTest(unittest.TestCase):
198 225 DIRECT_CAUSE_ERROR_CODE = """
199 226 try:
200 227 x = 1 + 2
201 228 print(not_defined_here)
202 229 except Exception as e:
203 230 x += 55
204 231 x - 1
205 232 y = {}
206 233 raise KeyError('uh') from e
207 234 """
208 235
209 236 EXCEPTION_DURING_HANDLING_CODE = """
210 237 try:
211 238 x = 1 + 2
212 239 print(not_defined_here)
213 240 except Exception as e:
214 241 x += 55
215 242 x - 1
216 243 y = {}
217 244 raise KeyError('uh')
218 245 """
219 246
220 247 SUPPRESS_CHAINING_CODE = """
221 248 try:
222 249 1/0
223 250 except Exception:
224 251 raise ValueError("Yikes") from None
225 252 """
226 253
227 254 def test_direct_cause_error(self):
228 255 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
229 256 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
230 257
231 258 def test_exception_during_handling_error(self):
232 259 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
233 260 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
234 261
235 262 def test_suppress_exception_chaining(self):
236 263 with tt.AssertNotPrints("ZeroDivisionError"), \
237 264 tt.AssertPrints("ValueError", suppress=False):
238 265 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
239 266
240 267
241 268 class RecursionTest(unittest.TestCase):
242 269 DEFINITIONS = """
243 270 def non_recurs():
244 271 1/0
245 272
246 273 def r1():
247 274 r1()
248 275
249 276 def r3a():
250 277 r3b()
251 278
252 279 def r3b():
253 280 r3c()
254 281
255 282 def r3c():
256 283 r3a()
257 284
258 285 def r3o1():
259 286 r3a()
260 287
261 288 def r3o2():
262 289 r3o1()
263 290 """
264 291 def setUp(self):
265 292 ip.run_cell(self.DEFINITIONS)
266 293
267 294 def test_no_recursion(self):
268 295 with tt.AssertNotPrints("frames repeated"):
269 296 ip.run_cell("non_recurs()")
270 297
271 298 def test_recursion_one_frame(self):
272 299 with tt.AssertPrints("1 frames repeated"):
273 300 ip.run_cell("r1()")
274 301
275 302 def test_recursion_three_frames(self):
276 303 with tt.AssertPrints("3 frames repeated"):
277 304 ip.run_cell("r3o2()")
278 305
279 306 def test_find_recursion(self):
280 307 captured = []
281 308 def capture_exc(*args, **kwargs):
282 309 captured.append(sys.exc_info())
283 310 with mock.patch.object(ip, 'showtraceback', capture_exc):
284 311 ip.run_cell("r3o2()")
285 312
286 313 self.assertEqual(len(captured), 1)
287 314 etype, evalue, tb = captured[0]
288 315 self.assertIn("recursion", str(evalue))
289 316
290 317 records = ip.InteractiveTB.get_records(tb, 3, ip.InteractiveTB.tb_offset)
291 318 for r in records[:10]:
292 319 print(r[1:4])
293 320
294 321 # The outermost frames should be:
295 322 # 0: the 'cell' that was running when the exception came up
296 323 # 1: r3o2()
297 324 # 2: r3o1()
298 325 # 3: r3a()
299 326 # Then repeating r3b, r3c, r3a
300 327 last_unique, repeat_length = find_recursion(etype, evalue, records)
301 328 self.assertEqual(last_unique, 2)
302 329 self.assertEqual(repeat_length, 3)
303 330
304 331
305 332 #----------------------------------------------------------------------------
306 333
307 334 # module testing (minimal)
308 335 def test_handlers():
309 336 def spam(c, d_e):
310 337 (d, e) = d_e
311 338 x = c + d
312 339 y = c * d
313 340 foo(x, y)
314 341
315 342 def foo(a, b, bar=1):
316 343 eggs(a, b + bar)
317 344
318 345 def eggs(f, g, z=globals()):
319 346 h = f + g
320 347 i = f - g
321 348 return h / i
322 349
323 350 buff = io.StringIO()
324 351
325 352 buff.write('')
326 353 buff.write('*** Before ***')
327 354 try:
328 355 buff.write(spam(1, (2, 3)))
329 356 except:
330 357 traceback.print_exc(file=buff)
331 358
332 359 handler = ColorTB(ostream=buff)
333 360 buff.write('*** ColorTB ***')
334 361 try:
335 362 buff.write(spam(1, (2, 3)))
336 363 except:
337 364 handler(*sys.exc_info())
338 365 buff.write('')
339 366
340 367 handler = VerboseTB(ostream=buff)
341 368 buff.write('*** VerboseTB ***')
342 369 try:
343 370 buff.write(spam(1, (2, 3)))
344 371 except:
345 372 handler(*sys.exc_info())
346 373 buff.write('')
347 374
General Comments 0
You need to be logged in to leave comments. Login now