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