1 # Copyright 2007 Google, Inc. All Rights Reserved.
2 # Licensed to PSF under a Contributor Agreement.
3
4 """Tests for the raise statement."""
5
6 from test import support
7 import sys
8 import types
9 import unittest
10
11
12 def get_tb():
13 try:
14 raise OSError()
15 except OSError as e:
16 return e.__traceback__
17
18
19 class ESC[4;38;5;81mContext:
20 def __enter__(self):
21 return self
22 def __exit__(self, exc_type, exc_value, exc_tb):
23 return True
24
25
26 class ESC[4;38;5;81mTestRaise(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
27 def test_invalid_reraise(self):
28 try:
29 raise
30 except RuntimeError as e:
31 self.assertIn("No active exception", str(e))
32 else:
33 self.fail("No exception raised")
34
35 def test_reraise(self):
36 try:
37 try:
38 raise IndexError()
39 except IndexError as e:
40 exc1 = e
41 raise
42 except IndexError as exc2:
43 self.assertIs(exc1, exc2)
44 else:
45 self.fail("No exception raised")
46
47 def test_except_reraise(self):
48 def reraise():
49 try:
50 raise TypeError("foo")
51 except:
52 try:
53 raise KeyError("caught")
54 except KeyError:
55 pass
56 raise
57 self.assertRaises(TypeError, reraise)
58
59 def test_finally_reraise(self):
60 def reraise():
61 try:
62 raise TypeError("foo")
63 except:
64 try:
65 raise KeyError("caught")
66 finally:
67 raise
68 self.assertRaises(KeyError, reraise)
69
70 def test_nested_reraise(self):
71 def nested_reraise():
72 raise
73 def reraise():
74 try:
75 raise TypeError("foo")
76 except:
77 nested_reraise()
78 self.assertRaises(TypeError, reraise)
79
80 def test_raise_from_None(self):
81 try:
82 try:
83 raise TypeError("foo")
84 except:
85 raise ValueError() from None
86 except ValueError as e:
87 self.assertIsInstance(e.__context__, TypeError)
88 self.assertIsNone(e.__cause__)
89
90 def test_with_reraise1(self):
91 def reraise():
92 try:
93 raise TypeError("foo")
94 except:
95 with Context():
96 pass
97 raise
98 self.assertRaises(TypeError, reraise)
99
100 def test_with_reraise2(self):
101 def reraise():
102 try:
103 raise TypeError("foo")
104 except:
105 with Context():
106 raise KeyError("caught")
107 raise
108 self.assertRaises(TypeError, reraise)
109
110 def test_yield_reraise(self):
111 def reraise():
112 try:
113 raise TypeError("foo")
114 except:
115 yield 1
116 raise
117 g = reraise()
118 next(g)
119 self.assertRaises(TypeError, lambda: next(g))
120 self.assertRaises(StopIteration, lambda: next(g))
121
122 def test_erroneous_exception(self):
123 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
124 def __init__(self):
125 raise RuntimeError()
126
127 try:
128 raise MyException
129 except RuntimeError:
130 pass
131 else:
132 self.fail("No exception raised")
133
134 def test_new_returns_invalid_instance(self):
135 # See issue #11627.
136 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
137 def __new__(cls, *args):
138 return object()
139
140 with self.assertRaises(TypeError):
141 raise MyException
142
143 def test_assert_with_tuple_arg(self):
144 try:
145 assert False, (3,)
146 except AssertionError as e:
147 self.assertEqual(str(e), "(3,)")
148
149
150
151 class ESC[4;38;5;81mTestCause(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
152
153 def testCauseSyntax(self):
154 try:
155 try:
156 try:
157 raise TypeError
158 except Exception:
159 raise ValueError from None
160 except ValueError as exc:
161 self.assertIsNone(exc.__cause__)
162 self.assertTrue(exc.__suppress_context__)
163 exc.__suppress_context__ = False
164 raise exc
165 except ValueError as exc:
166 e = exc
167
168 self.assertIsNone(e.__cause__)
169 self.assertFalse(e.__suppress_context__)
170 self.assertIsInstance(e.__context__, TypeError)
171
172 def test_invalid_cause(self):
173 try:
174 raise IndexError from 5
175 except TypeError as e:
176 self.assertIn("exception cause", str(e))
177 else:
178 self.fail("No exception raised")
179
180 def test_class_cause(self):
181 try:
182 raise IndexError from KeyError
183 except IndexError as e:
184 self.assertIsInstance(e.__cause__, KeyError)
185 else:
186 self.fail("No exception raised")
187
188 def test_instance_cause(self):
189 cause = KeyError()
190 try:
191 raise IndexError from cause
192 except IndexError as e:
193 self.assertIs(e.__cause__, cause)
194 else:
195 self.fail("No exception raised")
196
197 def test_erroneous_cause(self):
198 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
199 def __init__(self):
200 raise RuntimeError()
201
202 try:
203 raise IndexError from MyException
204 except RuntimeError:
205 pass
206 else:
207 self.fail("No exception raised")
208
209
210 class ESC[4;38;5;81mTestTraceback(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
211
212 def test_sets_traceback(self):
213 try:
214 raise IndexError()
215 except IndexError as e:
216 self.assertIsInstance(e.__traceback__, types.TracebackType)
217 else:
218 self.fail("No exception raised")
219
220 def test_accepts_traceback(self):
221 tb = get_tb()
222 try:
223 raise IndexError().with_traceback(tb)
224 except IndexError as e:
225 self.assertNotEqual(e.__traceback__, tb)
226 self.assertEqual(e.__traceback__.tb_next, tb)
227 else:
228 self.fail("No exception raised")
229
230
231 class ESC[4;38;5;81mTestTracebackType(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
232
233 def raiser(self):
234 raise ValueError
235
236 def test_attrs(self):
237 try:
238 self.raiser()
239 except Exception as exc:
240 tb = exc.__traceback__
241
242 self.assertIsInstance(tb.tb_next, types.TracebackType)
243 self.assertIs(tb.tb_frame, sys._getframe())
244 self.assertIsInstance(tb.tb_lasti, int)
245 self.assertIsInstance(tb.tb_lineno, int)
246
247 self.assertIs(tb.tb_next.tb_next, None)
248
249 # Invalid assignments
250 with self.assertRaises(TypeError):
251 del tb.tb_next
252
253 with self.assertRaises(TypeError):
254 tb.tb_next = "asdf"
255
256 # Loops
257 with self.assertRaises(ValueError):
258 tb.tb_next = tb
259
260 with self.assertRaises(ValueError):
261 tb.tb_next.tb_next = tb
262
263 # Valid assignments
264 tb.tb_next = None
265 self.assertIs(tb.tb_next, None)
266
267 new_tb = get_tb()
268 tb.tb_next = new_tb
269 self.assertIs(tb.tb_next, new_tb)
270
271 def test_constructor(self):
272 other_tb = get_tb()
273 frame = sys._getframe()
274
275 tb = types.TracebackType(other_tb, frame, 1, 2)
276 self.assertEqual(tb.tb_next, other_tb)
277 self.assertEqual(tb.tb_frame, frame)
278 self.assertEqual(tb.tb_lasti, 1)
279 self.assertEqual(tb.tb_lineno, 2)
280
281 tb = types.TracebackType(None, frame, 1, 2)
282 self.assertEqual(tb.tb_next, None)
283
284 with self.assertRaises(TypeError):
285 types.TracebackType("no", frame, 1, 2)
286
287 with self.assertRaises(TypeError):
288 types.TracebackType(other_tb, "no", 1, 2)
289
290 with self.assertRaises(TypeError):
291 types.TracebackType(other_tb, frame, "no", 2)
292
293 with self.assertRaises(TypeError):
294 types.TracebackType(other_tb, frame, 1, "nuh-uh")
295
296
297 class ESC[4;38;5;81mTestContext(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
298 def test_instance_context_instance_raise(self):
299 context = IndexError()
300 try:
301 try:
302 raise context
303 except:
304 raise OSError()
305 except OSError as e:
306 self.assertIs(e.__context__, context)
307 else:
308 self.fail("No exception raised")
309
310 def test_class_context_instance_raise(self):
311 context = IndexError
312 try:
313 try:
314 raise context
315 except:
316 raise OSError()
317 except OSError as e:
318 self.assertIsNot(e.__context__, context)
319 self.assertIsInstance(e.__context__, context)
320 else:
321 self.fail("No exception raised")
322
323 def test_class_context_class_raise(self):
324 context = IndexError
325 try:
326 try:
327 raise context
328 except:
329 raise OSError
330 except OSError as e:
331 self.assertIsNot(e.__context__, context)
332 self.assertIsInstance(e.__context__, context)
333 else:
334 self.fail("No exception raised")
335
336 def test_c_exception_context(self):
337 try:
338 try:
339 1/0
340 except:
341 raise OSError
342 except OSError as e:
343 self.assertIsInstance(e.__context__, ZeroDivisionError)
344 else:
345 self.fail("No exception raised")
346
347 def test_c_exception_raise(self):
348 try:
349 try:
350 1/0
351 except:
352 xyzzy
353 except NameError as e:
354 self.assertIsInstance(e.__context__, ZeroDivisionError)
355 else:
356 self.fail("No exception raised")
357
358 def test_noraise_finally(self):
359 try:
360 try:
361 pass
362 finally:
363 raise OSError
364 except OSError as e:
365 self.assertIsNone(e.__context__)
366 else:
367 self.fail("No exception raised")
368
369 def test_raise_finally(self):
370 try:
371 try:
372 1/0
373 finally:
374 raise OSError
375 except OSError as e:
376 self.assertIsInstance(e.__context__, ZeroDivisionError)
377 else:
378 self.fail("No exception raised")
379
380 def test_context_manager(self):
381 class ESC[4;38;5;81mContextManager:
382 def __enter__(self):
383 pass
384 def __exit__(self, t, v, tb):
385 xyzzy
386 try:
387 with ContextManager():
388 1/0
389 except NameError as e:
390 self.assertIsInstance(e.__context__, ZeroDivisionError)
391 else:
392 self.fail("No exception raised")
393
394 def test_cycle_broken(self):
395 # Self-cycles (when re-raising a caught exception) are broken
396 try:
397 try:
398 1/0
399 except ZeroDivisionError as e:
400 raise e
401 except ZeroDivisionError as e:
402 self.assertIsNone(e.__context__)
403
404 def test_reraise_cycle_broken(self):
405 # Non-trivial context cycles (through re-raising a previous exception)
406 # are broken too.
407 try:
408 try:
409 xyzzy
410 except NameError as a:
411 try:
412 1/0
413 except ZeroDivisionError:
414 raise a
415 except NameError as e:
416 self.assertIsNone(e.__context__.__context__)
417
418 def test_not_last(self):
419 # Context is not necessarily the last exception
420 context = Exception("context")
421 try:
422 raise context
423 except Exception:
424 try:
425 raise Exception("caught")
426 except Exception:
427 pass
428 try:
429 raise Exception("new")
430 except Exception as exc:
431 raised = exc
432 self.assertIs(raised.__context__, context)
433
434 def test_3118(self):
435 # deleting the generator caused the __context__ to be cleared
436 def gen():
437 try:
438 yield 1
439 finally:
440 pass
441
442 def f():
443 g = gen()
444 next(g)
445 try:
446 try:
447 raise ValueError
448 except:
449 del g
450 raise KeyError
451 except Exception as e:
452 self.assertIsInstance(e.__context__, ValueError)
453
454 f()
455
456 def test_3611(self):
457 import gc
458 # A re-raised exception in a __del__ caused the __context__
459 # to be cleared
460 class ESC[4;38;5;81mC:
461 def __del__(self):
462 try:
463 1/0
464 except:
465 raise
466
467 def f():
468 x = C()
469 try:
470 try:
471 f.x
472 except AttributeError:
473 # make x.__del__ trigger
474 del x
475 gc.collect() # For PyPy or other GCs.
476 raise TypeError
477 except Exception as e:
478 self.assertNotEqual(e.__context__, None)
479 self.assertIsInstance(e.__context__, AttributeError)
480
481 with support.catch_unraisable_exception() as cm:
482 f()
483
484 self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type)
485
486
487 class ESC[4;38;5;81mTestRemovedFunctionality(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
488 def test_tuples(self):
489 try:
490 raise (IndexError, KeyError) # This should be a tuple!
491 except TypeError:
492 pass
493 else:
494 self.fail("No exception raised")
495
496 def test_strings(self):
497 try:
498 raise "foo"
499 except TypeError:
500 pass
501 else:
502 self.fail("No exception raised")
503
504
505 if __name__ == "__main__":
506 unittest.main()