python (3.12.0)
1 # Python test set -- part 5, built-in exceptions
2
3 import copy
4 import os
5 import sys
6 import unittest
7 import pickle
8 import weakref
9 import errno
10 from textwrap import dedent
11
12 from test.support import (captured_stderr, check_impl_detail,
13 cpython_only, gc_collect,
14 no_tracing, script_helper,
15 SuppressCrashReport)
16 from test.support.import_helper import import_module
17 from test.support.os_helper import TESTFN, unlink
18 from test.support.warnings_helper import check_warnings
19 from test import support
20
21
22 class ESC[4;38;5;81mNaiveException(ESC[4;38;5;149mException):
23 def __init__(self, x):
24 self.x = x
25
26 class ESC[4;38;5;81mSlottedNaiveException(ESC[4;38;5;149mException):
27 __slots__ = ('x',)
28 def __init__(self, x):
29 self.x = x
30
31 class ESC[4;38;5;81mBrokenStrException(ESC[4;38;5;149mException):
32 def __str__(self):
33 raise Exception("str() is broken")
34
35 # XXX This is not really enough, each *operation* should be tested!
36
37 class ESC[4;38;5;81mExceptionTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
38
39 def raise_catch(self, exc, excname):
40 with self.subTest(exc=exc, excname=excname):
41 try:
42 raise exc("spam")
43 except exc as err:
44 buf1 = str(err)
45 try:
46 raise exc("spam")
47 except exc as err:
48 buf2 = str(err)
49 self.assertEqual(buf1, buf2)
50 self.assertEqual(exc.__name__, excname)
51
52 def testRaising(self):
53 self.raise_catch(AttributeError, "AttributeError")
54 self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
55
56 self.raise_catch(EOFError, "EOFError")
57 fp = open(TESTFN, 'w', encoding="utf-8")
58 fp.close()
59 fp = open(TESTFN, 'r', encoding="utf-8")
60 savestdin = sys.stdin
61 try:
62 try:
63 import marshal
64 marshal.loads(b'')
65 except EOFError:
66 pass
67 finally:
68 sys.stdin = savestdin
69 fp.close()
70 unlink(TESTFN)
71
72 self.raise_catch(OSError, "OSError")
73 self.assertRaises(OSError, open, 'this file does not exist', 'r')
74
75 self.raise_catch(ImportError, "ImportError")
76 self.assertRaises(ImportError, __import__, "undefined_module")
77
78 self.raise_catch(IndexError, "IndexError")
79 x = []
80 self.assertRaises(IndexError, x.__getitem__, 10)
81
82 self.raise_catch(KeyError, "KeyError")
83 x = {}
84 self.assertRaises(KeyError, x.__getitem__, 'key')
85
86 self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")
87
88 self.raise_catch(MemoryError, "MemoryError")
89
90 self.raise_catch(NameError, "NameError")
91 try: x = undefined_variable
92 except NameError: pass
93
94 self.raise_catch(OverflowError, "OverflowError")
95 x = 1
96 for dummy in range(128):
97 x += x # this simply shouldn't blow up
98
99 self.raise_catch(RuntimeError, "RuntimeError")
100 self.raise_catch(RecursionError, "RecursionError")
101
102 self.raise_catch(SyntaxError, "SyntaxError")
103 try: exec('/\n')
104 except SyntaxError: pass
105
106 self.raise_catch(IndentationError, "IndentationError")
107
108 self.raise_catch(TabError, "TabError")
109 try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n",
110 '<string>', 'exec')
111 except TabError: pass
112 else: self.fail("TabError not raised")
113
114 self.raise_catch(SystemError, "SystemError")
115
116 self.raise_catch(SystemExit, "SystemExit")
117 self.assertRaises(SystemExit, sys.exit, 0)
118
119 self.raise_catch(TypeError, "TypeError")
120 try: [] + ()
121 except TypeError: pass
122
123 self.raise_catch(ValueError, "ValueError")
124 self.assertRaises(ValueError, chr, 17<<16)
125
126 self.raise_catch(ZeroDivisionError, "ZeroDivisionError")
127 try: x = 1/0
128 except ZeroDivisionError: pass
129
130 self.raise_catch(Exception, "Exception")
131 try: x = 1/0
132 except Exception as e: pass
133
134 self.raise_catch(StopAsyncIteration, "StopAsyncIteration")
135
136 def testSyntaxErrorMessage(self):
137 # make sure the right exception message is raised for each of
138 # these code fragments
139
140 def ckmsg(src, msg):
141 with self.subTest(src=src, msg=msg):
142 try:
143 compile(src, '<fragment>', 'exec')
144 except SyntaxError as e:
145 if e.msg != msg:
146 self.fail("expected %s, got %s" % (msg, e.msg))
147 else:
148 self.fail("failed to get expected SyntaxError")
149
150 s = '''if 1:
151 try:
152 continue
153 except:
154 pass'''
155
156 ckmsg(s, "'continue' not properly in loop")
157 ckmsg("continue\n", "'continue' not properly in loop")
158 ckmsg("f'{6 0}'", "invalid syntax. Perhaps you forgot a comma?")
159
160 def testSyntaxErrorMissingParens(self):
161 def ckmsg(src, msg, exception=SyntaxError):
162 try:
163 compile(src, '<fragment>', 'exec')
164 except exception as e:
165 if e.msg != msg:
166 self.fail("expected %s, got %s" % (msg, e.msg))
167 else:
168 self.fail("failed to get expected SyntaxError")
169
170 s = '''print "old style"'''
171 ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?")
172
173 s = '''print "old style",'''
174 ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?")
175
176 s = 'print f(a+b,c)'
177 ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?")
178
179 s = '''exec "old style"'''
180 ckmsg(s, "Missing parentheses in call to 'exec'. Did you mean exec(...)?")
181
182 s = 'exec f(a+b,c)'
183 ckmsg(s, "Missing parentheses in call to 'exec'. Did you mean exec(...)?")
184
185 # Check that we don't incorrectly identify '(...)' as an expression to the right
186 # of 'print'
187
188 s = 'print (a+b,c) $ 42'
189 ckmsg(s, "invalid syntax")
190
191 s = 'exec (a+b,c) $ 42'
192 ckmsg(s, "invalid syntax")
193
194 # should not apply to subclasses, see issue #31161
195 s = '''if True:\nprint "No indent"'''
196 ckmsg(s, "expected an indented block after 'if' statement on line 1", IndentationError)
197
198 s = '''if True:\n print()\n\texec "mixed tabs and spaces"'''
199 ckmsg(s, "inconsistent use of tabs and spaces in indentation", TabError)
200
201 def check(self, src, lineno, offset, end_lineno=None, end_offset=None, encoding='utf-8'):
202 with self.subTest(source=src, lineno=lineno, offset=offset):
203 with self.assertRaises(SyntaxError) as cm:
204 compile(src, '<fragment>', 'exec')
205 self.assertEqual(cm.exception.lineno, lineno)
206 self.assertEqual(cm.exception.offset, offset)
207 if end_lineno is not None:
208 self.assertEqual(cm.exception.end_lineno, end_lineno)
209 if end_offset is not None:
210 self.assertEqual(cm.exception.end_offset, end_offset)
211
212 if cm.exception.text is not None:
213 if not isinstance(src, str):
214 src = src.decode(encoding, 'replace')
215 line = src.split('\n')[lineno-1]
216 self.assertIn(line, cm.exception.text)
217
218 def test_error_offset_continuation_characters(self):
219 check = self.check
220 check('"\\\n"(1 for c in I,\\\n\\', 2, 2)
221
222 def testSyntaxErrorOffset(self):
223 check = self.check
224 check('def fact(x):\n\treturn x!\n', 2, 10)
225 check('1 +\n', 1, 4)
226 check('def spam():\n print(1)\n print(2)', 3, 10)
227 check('Python = "Python" +', 1, 20)
228 check('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', 1, 20)
229 check(b'# -*- coding: cp1251 -*-\nPython = "\xcf\xb3\xf2\xee\xed" +',
230 2, 19, encoding='cp1251')
231 check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 10)
232 check('x = "a', 1, 5)
233 check('lambda x: x = 2', 1, 1)
234 check('f{a + b + c}', 1, 2)
235 check('[file for str(file) in []\n]', 1, 11)
236 check('a = « hello » « world »', 1, 5)
237 check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5)
238 check('[file for\n str(file) in []]', 2, 2)
239 check("ages = {'Alice'=22, 'Bob'=23}", 1, 9)
240 check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19)
241 check("[a b c d e f]", 1, 2)
242 check("for x yfff:", 1, 7)
243 check("f(a for a in b, c)", 1, 3, 1, 15)
244 check("f(a for a in b if a, c)", 1, 3, 1, 20)
245 check("f(a, b for b in c)", 1, 6, 1, 18)
246 check("f(a, b for b in c, d)", 1, 6, 1, 18)
247
248 # Errors thrown by compile.c
249 check('class foo:return 1', 1, 11)
250 check('def f():\n continue', 2, 3)
251 check('def f():\n break', 2, 3)
252 check('try:\n pass\nexcept:\n pass\nexcept ValueError:\n pass', 3, 1)
253 check('try:\n pass\nexcept*:\n pass', 3, 8)
254 check('try:\n pass\nexcept*:\n pass\nexcept* ValueError:\n pass', 3, 8)
255
256 # Errors thrown by tokenizer.c
257 check('(0x+1)', 1, 3)
258 check('x = 0xI', 1, 6)
259 check('0010 + 2', 1, 1)
260 check('x = 32e-+4', 1, 8)
261 check('x = 0o9', 1, 7)
262 check('\u03b1 = 0xI', 1, 6)
263 check(b'\xce\xb1 = 0xI', 1, 6)
264 check(b'# -*- coding: iso8859-7 -*-\n\xe1 = 0xI', 2, 6,
265 encoding='iso8859-7')
266 check(b"""if 1:
267 def foo():
268 '''
269
270 def bar():
271 pass
272
273 def baz():
274 '''quux'''
275 """, 9, 24)
276 check("pass\npass\npass\n(1+)\npass\npass\npass", 4, 4)
277 check("(1+)", 1, 4)
278 check("[interesting\nfoo()\n", 1, 1)
279 check(b"\xef\xbb\xbf#coding: utf8\nprint('\xe6\x88\x91')\n", 0, -1)
280 check("""f'''
281 {
282 (123_a)
283 }'''""", 3, 17)
284 check("""f'''
285 {
286 f\"\"\"
287 {
288 (123_a)
289 }
290 \"\"\"
291 }'''""", 5, 17)
292 check('''f"""
293
294
295 {
296 6
297 0="""''', 5, 13)
298
299 # Errors thrown by symtable.c
300 check('x = [(yield i) for i in range(3)]', 1, 7)
301 check('def f():\n from _ import *', 2, 17)
302 check('def f(x, x):\n pass', 1, 10)
303 check('{i for i in range(5) if (j := 0) for j in range(5)}', 1, 38)
304 check('def f(x):\n nonlocal x', 2, 3)
305 check('def f(x):\n x = 1\n global x', 3, 3)
306 check('nonlocal x', 1, 1)
307 check('def f():\n global x\n nonlocal x', 2, 3)
308
309 # Errors thrown by future.c
310 check('from __future__ import doesnt_exist', 1, 1)
311 check('from __future__ import braces', 1, 1)
312 check('x=1\nfrom __future__ import division', 2, 1)
313 check('foo(1=2)', 1, 5)
314 check('def f():\n x, y: int', 2, 3)
315 check('[*x for x in xs]', 1, 2)
316 check('foo(x for x in range(10), 100)', 1, 5)
317 check('for 1 in []: pass', 1, 5)
318 check('(yield i) = 2', 1, 2)
319 check('def f(*):\n pass', 1, 7)
320
321 @cpython_only
322 def testSettingException(self):
323 # test that setting an exception at the C level works even if the
324 # exception object can't be constructed.
325
326 class ESC[4;38;5;81mBadException(ESC[4;38;5;149mException):
327 def __init__(self_):
328 raise RuntimeError("can't instantiate BadException")
329
330 class ESC[4;38;5;81mInvalidException:
331 pass
332
333 def test_capi1():
334 import _testcapi
335 try:
336 _testcapi.raise_exception(BadException, 1)
337 except TypeError as err:
338 co = err.__traceback__.tb_frame.f_code
339 self.assertEqual(co.co_name, "test_capi1")
340 self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
341 else:
342 self.fail("Expected exception")
343
344 def test_capi2():
345 import _testcapi
346 try:
347 _testcapi.raise_exception(BadException, 0)
348 except RuntimeError as err:
349 tb = err.__traceback__.tb_next
350 co = tb.tb_frame.f_code
351 self.assertEqual(co.co_name, "__init__")
352 self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
353 co2 = tb.tb_frame.f_back.f_code
354 self.assertEqual(co2.co_name, "test_capi2")
355 else:
356 self.fail("Expected exception")
357
358 def test_capi3():
359 import _testcapi
360 self.assertRaises(SystemError, _testcapi.raise_exception,
361 InvalidException, 1)
362
363 test_capi1()
364 test_capi2()
365 test_capi3()
366
367 def test_WindowsError(self):
368 try:
369 WindowsError
370 except NameError:
371 pass
372 else:
373 self.assertIs(WindowsError, OSError)
374 self.assertEqual(str(OSError(1001)), "1001")
375 self.assertEqual(str(OSError(1001, "message")),
376 "[Errno 1001] message")
377 # POSIX errno (9 aka EBADF) is untranslated
378 w = OSError(9, 'foo', 'bar')
379 self.assertEqual(w.errno, 9)
380 self.assertEqual(w.winerror, None)
381 self.assertEqual(str(w), "[Errno 9] foo: 'bar'")
382 # ERROR_PATH_NOT_FOUND (win error 3) becomes ENOENT (2)
383 w = OSError(0, 'foo', 'bar', 3)
384 self.assertEqual(w.errno, 2)
385 self.assertEqual(w.winerror, 3)
386 self.assertEqual(w.strerror, 'foo')
387 self.assertEqual(w.filename, 'bar')
388 self.assertEqual(w.filename2, None)
389 self.assertEqual(str(w), "[WinError 3] foo: 'bar'")
390 # Unknown win error becomes EINVAL (22)
391 w = OSError(0, 'foo', None, 1001)
392 self.assertEqual(w.errno, 22)
393 self.assertEqual(w.winerror, 1001)
394 self.assertEqual(w.strerror, 'foo')
395 self.assertEqual(w.filename, None)
396 self.assertEqual(w.filename2, None)
397 self.assertEqual(str(w), "[WinError 1001] foo")
398 # Non-numeric "errno"
399 w = OSError('bar', 'foo')
400 self.assertEqual(w.errno, 'bar')
401 self.assertEqual(w.winerror, None)
402 self.assertEqual(w.strerror, 'foo')
403 self.assertEqual(w.filename, None)
404 self.assertEqual(w.filename2, None)
405
406 @unittest.skipUnless(sys.platform == 'win32',
407 'test specific to Windows')
408 def test_windows_message(self):
409 """Should fill in unknown error code in Windows error message"""
410 ctypes = import_module('ctypes')
411 # this error code has no message, Python formats it as hexadecimal
412 code = 3765269347
413 with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code):
414 ctypes.pythonapi.PyErr_SetFromWindowsErr(code)
415
416 def testAttributes(self):
417 # test that exception attributes are happy
418
419 exceptionList = [
420 (BaseException, (), {}, {'args' : ()}),
421 (BaseException, (1, ), {}, {'args' : (1,)}),
422 (BaseException, ('foo',), {},
423 {'args' : ('foo',)}),
424 (BaseException, ('foo', 1), {},
425 {'args' : ('foo', 1)}),
426 (SystemExit, ('foo',), {},
427 {'args' : ('foo',), 'code' : 'foo'}),
428 (OSError, ('foo',), {},
429 {'args' : ('foo',), 'filename' : None, 'filename2' : None,
430 'errno' : None, 'strerror' : None}),
431 (OSError, ('foo', 'bar'), {},
432 {'args' : ('foo', 'bar'),
433 'filename' : None, 'filename2' : None,
434 'errno' : 'foo', 'strerror' : 'bar'}),
435 (OSError, ('foo', 'bar', 'baz'), {},
436 {'args' : ('foo', 'bar'),
437 'filename' : 'baz', 'filename2' : None,
438 'errno' : 'foo', 'strerror' : 'bar'}),
439 (OSError, ('foo', 'bar', 'baz', None, 'quux'), {},
440 {'args' : ('foo', 'bar'), 'filename' : 'baz', 'filename2': 'quux'}),
441 (OSError, ('errnoStr', 'strErrorStr', 'filenameStr'), {},
442 {'args' : ('errnoStr', 'strErrorStr'),
443 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
444 'filename' : 'filenameStr'}),
445 (OSError, (1, 'strErrorStr', 'filenameStr'), {},
446 {'args' : (1, 'strErrorStr'), 'errno' : 1,
447 'strerror' : 'strErrorStr',
448 'filename' : 'filenameStr', 'filename2' : None}),
449 (SyntaxError, (), {}, {'msg' : None, 'text' : None,
450 'filename' : None, 'lineno' : None, 'offset' : None,
451 'end_offset': None, 'print_file_and_line' : None}),
452 (SyntaxError, ('msgStr',), {},
453 {'args' : ('msgStr',), 'text' : None,
454 'print_file_and_line' : None, 'msg' : 'msgStr',
455 'filename' : None, 'lineno' : None, 'offset' : None,
456 'end_offset': None}),
457 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
458 'textStr', 'endLinenoStr', 'endOffsetStr')), {},
459 {'offset' : 'offsetStr', 'text' : 'textStr',
460 'args' : ('msgStr', ('filenameStr', 'linenoStr',
461 'offsetStr', 'textStr',
462 'endLinenoStr', 'endOffsetStr')),
463 'print_file_and_line' : None, 'msg' : 'msgStr',
464 'filename' : 'filenameStr', 'lineno' : 'linenoStr',
465 'end_lineno': 'endLinenoStr', 'end_offset': 'endOffsetStr'}),
466 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
467 'textStr', 'endLinenoStr', 'endOffsetStr',
468 'print_file_and_lineStr'), {},
469 {'text' : None,
470 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
471 'textStr', 'endLinenoStr', 'endOffsetStr',
472 'print_file_and_lineStr'),
473 'print_file_and_line' : None, 'msg' : 'msgStr',
474 'filename' : None, 'lineno' : None, 'offset' : None,
475 'end_lineno': None, 'end_offset': None}),
476 (UnicodeError, (), {}, {'args' : (),}),
477 (UnicodeEncodeError, ('ascii', 'a', 0, 1,
478 'ordinal not in range'), {},
479 {'args' : ('ascii', 'a', 0, 1,
480 'ordinal not in range'),
481 'encoding' : 'ascii', 'object' : 'a',
482 'start' : 0, 'reason' : 'ordinal not in range'}),
483 (UnicodeDecodeError, ('ascii', bytearray(b'\xff'), 0, 1,
484 'ordinal not in range'), {},
485 {'args' : ('ascii', bytearray(b'\xff'), 0, 1,
486 'ordinal not in range'),
487 'encoding' : 'ascii', 'object' : b'\xff',
488 'start' : 0, 'reason' : 'ordinal not in range'}),
489 (UnicodeDecodeError, ('ascii', b'\xff', 0, 1,
490 'ordinal not in range'), {},
491 {'args' : ('ascii', b'\xff', 0, 1,
492 'ordinal not in range'),
493 'encoding' : 'ascii', 'object' : b'\xff',
494 'start' : 0, 'reason' : 'ordinal not in range'}),
495 (UnicodeTranslateError, ("\u3042", 0, 1, "ouch"), {},
496 {'args' : ('\u3042', 0, 1, 'ouch'),
497 'object' : '\u3042', 'reason' : 'ouch',
498 'start' : 0, 'end' : 1}),
499 (NaiveException, ('foo',), {},
500 {'args': ('foo',), 'x': 'foo'}),
501 (SlottedNaiveException, ('foo',), {},
502 {'args': ('foo',), 'x': 'foo'}),
503 (AttributeError, ('foo',), dict(name='name', obj='obj'),
504 dict(args=('foo',), name='name', obj='obj')),
505 ]
506 try:
507 # More tests are in test_WindowsError
508 exceptionList.append(
509 (WindowsError, (1, 'strErrorStr', 'filenameStr'), {},
510 {'args' : (1, 'strErrorStr'),
511 'strerror' : 'strErrorStr', 'winerror' : None,
512 'errno' : 1,
513 'filename' : 'filenameStr', 'filename2' : None})
514 )
515 except NameError:
516 pass
517
518 for exc, args, kwargs, expected in exceptionList:
519 try:
520 e = exc(*args, **kwargs)
521 except:
522 print(f"\nexc={exc!r}, args={args!r}", file=sys.stderr)
523 # raise
524 else:
525 # Verify module name
526 if not type(e).__name__.endswith('NaiveException'):
527 self.assertEqual(type(e).__module__, 'builtins')
528 # Verify no ref leaks in Exc_str()
529 s = str(e)
530 for checkArgName in expected:
531 value = getattr(e, checkArgName)
532 self.assertEqual(repr(value),
533 repr(expected[checkArgName]),
534 '%r.%s == %r, expected %r' % (
535 e, checkArgName,
536 value, expected[checkArgName]))
537
538 # test for pickling support
539 for p in [pickle]:
540 for protocol in range(p.HIGHEST_PROTOCOL + 1):
541 s = p.dumps(e, protocol)
542 new = p.loads(s)
543 for checkArgName in expected:
544 got = repr(getattr(new, checkArgName))
545 if exc == AttributeError and checkArgName == 'obj':
546 # See GH-103352, we're not pickling
547 # obj at this point. So verify it's None.
548 want = repr(None)
549 else:
550 want = repr(expected[checkArgName])
551 self.assertEqual(got, want,
552 'pickled "%r", attribute "%s' %
553 (e, checkArgName))
554
555 def test_setstate(self):
556 e = Exception(42)
557 e.blah = 53
558 self.assertEqual(e.args, (42,))
559 self.assertEqual(e.blah, 53)
560 self.assertRaises(AttributeError, getattr, e, 'a')
561 self.assertRaises(AttributeError, getattr, e, 'b')
562 e.__setstate__({'a': 1 , 'b': 2})
563 self.assertEqual(e.args, (42,))
564 self.assertEqual(e.blah, 53)
565 self.assertEqual(e.a, 1)
566 self.assertEqual(e.b, 2)
567 e.__setstate__({'a': 11, 'args': (1,2,3), 'blah': 35})
568 self.assertEqual(e.args, (1,2,3))
569 self.assertEqual(e.blah, 35)
570 self.assertEqual(e.a, 11)
571 self.assertEqual(e.b, 2)
572
573 def test_invalid_setstate(self):
574 e = Exception(42)
575 with self.assertRaisesRegex(TypeError, "state is not a dictionary"):
576 e.__setstate__(42)
577
578 def test_notes(self):
579 for e in [BaseException(1), Exception(2), ValueError(3)]:
580 with self.subTest(e=e):
581 self.assertFalse(hasattr(e, '__notes__'))
582 e.add_note("My Note")
583 self.assertEqual(e.__notes__, ["My Note"])
584
585 with self.assertRaises(TypeError):
586 e.add_note(42)
587 self.assertEqual(e.__notes__, ["My Note"])
588
589 e.add_note("Your Note")
590 self.assertEqual(e.__notes__, ["My Note", "Your Note"])
591
592 del e.__notes__
593 self.assertFalse(hasattr(e, '__notes__'))
594
595 e.add_note("Our Note")
596 self.assertEqual(e.__notes__, ["Our Note"])
597
598 e.__notes__ = 42
599 self.assertEqual(e.__notes__, 42)
600
601 with self.assertRaises(TypeError):
602 e.add_note("will not work")
603 self.assertEqual(e.__notes__, 42)
604
605 def testWithTraceback(self):
606 try:
607 raise IndexError(4)
608 except Exception as e:
609 tb = e.__traceback__
610
611 e = BaseException().with_traceback(tb)
612 self.assertIsInstance(e, BaseException)
613 self.assertEqual(e.__traceback__, tb)
614
615 e = IndexError(5).with_traceback(tb)
616 self.assertIsInstance(e, IndexError)
617 self.assertEqual(e.__traceback__, tb)
618
619 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
620 pass
621
622 e = MyException().with_traceback(tb)
623 self.assertIsInstance(e, MyException)
624 self.assertEqual(e.__traceback__, tb)
625
626 def testInvalidTraceback(self):
627 try:
628 Exception().__traceback__ = 5
629 except TypeError as e:
630 self.assertIn("__traceback__ must be a traceback", str(e))
631 else:
632 self.fail("No exception raised")
633
634 def test_invalid_setattr(self):
635 TE = TypeError
636 exc = Exception()
637 msg = "'int' object is not iterable"
638 self.assertRaisesRegex(TE, msg, setattr, exc, 'args', 1)
639 msg = "__traceback__ must be a traceback or None"
640 self.assertRaisesRegex(TE, msg, setattr, exc, '__traceback__', 1)
641 msg = "exception cause must be None or derive from BaseException"
642 self.assertRaisesRegex(TE, msg, setattr, exc, '__cause__', 1)
643 msg = "exception context must be None or derive from BaseException"
644 self.assertRaisesRegex(TE, msg, setattr, exc, '__context__', 1)
645
646 def test_invalid_delattr(self):
647 TE = TypeError
648 try:
649 raise IndexError(4)
650 except Exception as e:
651 exc = e
652
653 msg = "may not be deleted"
654 self.assertRaisesRegex(TE, msg, delattr, exc, 'args')
655 self.assertRaisesRegex(TE, msg, delattr, exc, '__traceback__')
656 self.assertRaisesRegex(TE, msg, delattr, exc, '__cause__')
657 self.assertRaisesRegex(TE, msg, delattr, exc, '__context__')
658
659 def testNoneClearsTracebackAttr(self):
660 try:
661 raise IndexError(4)
662 except Exception as e:
663 tb = e.__traceback__
664
665 e = Exception()
666 e.__traceback__ = tb
667 e.__traceback__ = None
668 self.assertEqual(e.__traceback__, None)
669
670 def testChainingAttrs(self):
671 e = Exception()
672 self.assertIsNone(e.__context__)
673 self.assertIsNone(e.__cause__)
674
675 e = TypeError()
676 self.assertIsNone(e.__context__)
677 self.assertIsNone(e.__cause__)
678
679 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mOSError):
680 pass
681
682 e = MyException()
683 self.assertIsNone(e.__context__)
684 self.assertIsNone(e.__cause__)
685
686 def testChainingDescriptors(self):
687 try:
688 raise Exception()
689 except Exception as exc:
690 e = exc
691
692 self.assertIsNone(e.__context__)
693 self.assertIsNone(e.__cause__)
694 self.assertFalse(e.__suppress_context__)
695
696 e.__context__ = NameError()
697 e.__cause__ = None
698 self.assertIsInstance(e.__context__, NameError)
699 self.assertIsNone(e.__cause__)
700 self.assertTrue(e.__suppress_context__)
701 e.__suppress_context__ = False
702 self.assertFalse(e.__suppress_context__)
703
704 def testKeywordArgs(self):
705 # test that builtin exception don't take keyword args,
706 # but user-defined subclasses can if they want
707 self.assertRaises(TypeError, BaseException, a=1)
708
709 class ESC[4;38;5;81mDerivedException(ESC[4;38;5;149mBaseException):
710 def __init__(self, fancy_arg):
711 BaseException.__init__(self)
712 self.fancy_arg = fancy_arg
713
714 x = DerivedException(fancy_arg=42)
715 self.assertEqual(x.fancy_arg, 42)
716
717 @no_tracing
718 def testInfiniteRecursion(self):
719 def f():
720 return f()
721 self.assertRaises(RecursionError, f)
722
723 def g():
724 try:
725 return g()
726 except ValueError:
727 return -1
728 self.assertRaises(RecursionError, g)
729
730 def test_str(self):
731 # Make sure both instances and classes have a str representation.
732 self.assertTrue(str(Exception))
733 self.assertTrue(str(Exception('a')))
734 self.assertTrue(str(Exception('a', 'b')))
735
736 def test_exception_cleanup_names(self):
737 # Make sure the local variable bound to the exception instance by
738 # an "except" statement is only visible inside the except block.
739 try:
740 raise Exception()
741 except Exception as e:
742 self.assertIsInstance(e, Exception)
743 self.assertNotIn('e', locals())
744 with self.assertRaises(UnboundLocalError):
745 e
746
747 def test_exception_cleanup_names2(self):
748 # Make sure the cleanup doesn't break if the variable is explicitly deleted.
749 try:
750 raise Exception()
751 except Exception as e:
752 self.assertIsInstance(e, Exception)
753 del e
754 self.assertNotIn('e', locals())
755 with self.assertRaises(UnboundLocalError):
756 e
757
758 def testExceptionCleanupState(self):
759 # Make sure exception state is cleaned up as soon as the except
760 # block is left. See #2507
761
762 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
763 def __init__(self, obj):
764 self.obj = obj
765 class ESC[4;38;5;81mMyObj:
766 pass
767
768 def inner_raising_func():
769 # Create some references in exception value and traceback
770 local_ref = obj
771 raise MyException(obj)
772
773 # Qualified "except" with "as"
774 obj = MyObj()
775 wr = weakref.ref(obj)
776 try:
777 inner_raising_func()
778 except MyException as e:
779 pass
780 obj = None
781 gc_collect() # For PyPy or other GCs.
782 obj = wr()
783 self.assertIsNone(obj)
784
785 # Qualified "except" without "as"
786 obj = MyObj()
787 wr = weakref.ref(obj)
788 try:
789 inner_raising_func()
790 except MyException:
791 pass
792 obj = None
793 gc_collect() # For PyPy or other GCs.
794 obj = wr()
795 self.assertIsNone(obj)
796
797 # Bare "except"
798 obj = MyObj()
799 wr = weakref.ref(obj)
800 try:
801 inner_raising_func()
802 except:
803 pass
804 obj = None
805 gc_collect() # For PyPy or other GCs.
806 obj = wr()
807 self.assertIsNone(obj)
808
809 # "except" with premature block leave
810 obj = MyObj()
811 wr = weakref.ref(obj)
812 for i in [0]:
813 try:
814 inner_raising_func()
815 except:
816 break
817 obj = None
818 gc_collect() # For PyPy or other GCs.
819 obj = wr()
820 self.assertIsNone(obj)
821
822 # "except" block raising another exception
823 obj = MyObj()
824 wr = weakref.ref(obj)
825 try:
826 try:
827 inner_raising_func()
828 except:
829 raise KeyError
830 except KeyError as e:
831 # We want to test that the except block above got rid of
832 # the exception raised in inner_raising_func(), but it
833 # also ends up in the __context__ of the KeyError, so we
834 # must clear the latter manually for our test to succeed.
835 e.__context__ = None
836 obj = None
837 gc_collect() # For PyPy or other GCs.
838 obj = wr()
839 # guarantee no ref cycles on CPython (don't gc_collect)
840 if check_impl_detail(cpython=False):
841 gc_collect()
842 self.assertIsNone(obj)
843
844 # Some complicated construct
845 obj = MyObj()
846 wr = weakref.ref(obj)
847 try:
848 inner_raising_func()
849 except MyException:
850 try:
851 try:
852 raise
853 finally:
854 raise
855 except MyException:
856 pass
857 obj = None
858 if check_impl_detail(cpython=False):
859 gc_collect()
860 obj = wr()
861 self.assertIsNone(obj)
862
863 # Inside an exception-silencing "with" block
864 class ESC[4;38;5;81mContext:
865 def __enter__(self):
866 return self
867 def __exit__ (self, exc_type, exc_value, exc_tb):
868 return True
869 obj = MyObj()
870 wr = weakref.ref(obj)
871 with Context():
872 inner_raising_func()
873 obj = None
874 if check_impl_detail(cpython=False):
875 gc_collect()
876 obj = wr()
877 self.assertIsNone(obj)
878
879 def test_exception_target_in_nested_scope(self):
880 # issue 4617: This used to raise a SyntaxError
881 # "can not delete variable 'e' referenced in nested scope"
882 def print_error():
883 e
884 try:
885 something
886 except Exception as e:
887 print_error()
888 # implicit "del e" here
889
890 def test_generator_leaking(self):
891 # Test that generator exception state doesn't leak into the calling
892 # frame
893 def yield_raise():
894 try:
895 raise KeyError("caught")
896 except KeyError:
897 yield sys.exception()
898 yield sys.exception()
899 yield sys.exception()
900 g = yield_raise()
901 self.assertIsInstance(next(g), KeyError)
902 self.assertIsNone(sys.exception())
903 self.assertIsInstance(next(g), KeyError)
904 self.assertIsNone(sys.exception())
905 self.assertIsNone(next(g))
906
907 # Same test, but inside an exception handler
908 try:
909 raise TypeError("foo")
910 except TypeError:
911 g = yield_raise()
912 self.assertIsInstance(next(g), KeyError)
913 self.assertIsInstance(sys.exception(), TypeError)
914 self.assertIsInstance(next(g), KeyError)
915 self.assertIsInstance(sys.exception(), TypeError)
916 self.assertIsInstance(next(g), TypeError)
917 del g
918 self.assertIsInstance(sys.exception(), TypeError)
919
920 def test_generator_leaking2(self):
921 # See issue 12475.
922 def g():
923 yield
924 try:
925 raise RuntimeError
926 except RuntimeError:
927 it = g()
928 next(it)
929 try:
930 next(it)
931 except StopIteration:
932 pass
933 self.assertIsNone(sys.exception())
934
935 def test_generator_leaking3(self):
936 # See issue #23353. When gen.throw() is called, the caller's
937 # exception state should be save and restored.
938 def g():
939 try:
940 yield
941 except ZeroDivisionError:
942 yield sys.exception()
943 it = g()
944 next(it)
945 try:
946 1/0
947 except ZeroDivisionError as e:
948 self.assertIs(sys.exception(), e)
949 gen_exc = it.throw(e)
950 self.assertIs(sys.exception(), e)
951 self.assertIs(gen_exc, e)
952 self.assertIsNone(sys.exception())
953
954 def test_generator_leaking4(self):
955 # See issue #23353. When an exception is raised by a generator,
956 # the caller's exception state should still be restored.
957 def g():
958 try:
959 1/0
960 except ZeroDivisionError:
961 yield sys.exception()
962 raise
963 it = g()
964 try:
965 raise TypeError
966 except TypeError:
967 # The caller's exception state (TypeError) is temporarily
968 # saved in the generator.
969 tp = type(next(it))
970 self.assertIs(tp, ZeroDivisionError)
971 try:
972 next(it)
973 # We can't check it immediately, but while next() returns
974 # with an exception, it shouldn't have restored the old
975 # exception state (TypeError).
976 except ZeroDivisionError as e:
977 self.assertIs(sys.exception(), e)
978 # We used to find TypeError here.
979 self.assertIsNone(sys.exception())
980
981 def test_generator_doesnt_retain_old_exc(self):
982 def g():
983 self.assertIsInstance(sys.exception(), RuntimeError)
984 yield
985 self.assertIsNone(sys.exception())
986 it = g()
987 try:
988 raise RuntimeError
989 except RuntimeError:
990 next(it)
991 self.assertRaises(StopIteration, next, it)
992
993 def test_generator_finalizing_and_sys_exception(self):
994 # See #7173
995 def simple_gen():
996 yield 1
997 def run_gen():
998 gen = simple_gen()
999 try:
1000 raise RuntimeError
1001 except RuntimeError:
1002 return next(gen)
1003 run_gen()
1004 gc_collect()
1005 self.assertIsNone(sys.exception())
1006
1007 def _check_generator_cleanup_exc_state(self, testfunc):
1008 # Issue #12791: exception state is cleaned up as soon as a generator
1009 # is closed (reference cycles are broken).
1010 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException):
1011 def __init__(self, obj):
1012 self.obj = obj
1013 class ESC[4;38;5;81mMyObj:
1014 pass
1015
1016 def raising_gen():
1017 try:
1018 raise MyException(obj)
1019 except MyException:
1020 yield
1021
1022 obj = MyObj()
1023 wr = weakref.ref(obj)
1024 g = raising_gen()
1025 next(g)
1026 testfunc(g)
1027 g = obj = None
1028 gc_collect() # For PyPy or other GCs.
1029 obj = wr()
1030 self.assertIsNone(obj)
1031
1032 def test_generator_throw_cleanup_exc_state(self):
1033 def do_throw(g):
1034 try:
1035 g.throw(RuntimeError())
1036 except RuntimeError:
1037 pass
1038 self._check_generator_cleanup_exc_state(do_throw)
1039
1040 def test_generator_close_cleanup_exc_state(self):
1041 def do_close(g):
1042 g.close()
1043 self._check_generator_cleanup_exc_state(do_close)
1044
1045 def test_generator_del_cleanup_exc_state(self):
1046 def do_del(g):
1047 g = None
1048 self._check_generator_cleanup_exc_state(do_del)
1049
1050 def test_generator_next_cleanup_exc_state(self):
1051 def do_next(g):
1052 try:
1053 next(g)
1054 except StopIteration:
1055 pass
1056 else:
1057 self.fail("should have raised StopIteration")
1058 self._check_generator_cleanup_exc_state(do_next)
1059
1060 def test_generator_send_cleanup_exc_state(self):
1061 def do_send(g):
1062 try:
1063 g.send(None)
1064 except StopIteration:
1065 pass
1066 else:
1067 self.fail("should have raised StopIteration")
1068 self._check_generator_cleanup_exc_state(do_send)
1069
1070 def test_3114(self):
1071 # Bug #3114: in its destructor, MyObject retrieves a pointer to
1072 # obsolete and/or deallocated objects.
1073 class ESC[4;38;5;81mMyObject:
1074 def __del__(self):
1075 nonlocal e
1076 e = sys.exception()
1077 e = ()
1078 try:
1079 raise Exception(MyObject())
1080 except:
1081 pass
1082 gc_collect() # For PyPy or other GCs.
1083 self.assertIsNone(e)
1084
1085 def test_raise_does_not_create_context_chain_cycle(self):
1086 class ESC[4;38;5;81mA(ESC[4;38;5;149mException):
1087 pass
1088 class ESC[4;38;5;81mB(ESC[4;38;5;149mException):
1089 pass
1090 class ESC[4;38;5;81mC(ESC[4;38;5;149mException):
1091 pass
1092
1093 # Create a context chain:
1094 # C -> B -> A
1095 # Then raise A in context of C.
1096 try:
1097 try:
1098 raise A
1099 except A as a_:
1100 a = a_
1101 try:
1102 raise B
1103 except B as b_:
1104 b = b_
1105 try:
1106 raise C
1107 except C as c_:
1108 c = c_
1109 self.assertIsInstance(a, A)
1110 self.assertIsInstance(b, B)
1111 self.assertIsInstance(c, C)
1112 self.assertIsNone(a.__context__)
1113 self.assertIs(b.__context__, a)
1114 self.assertIs(c.__context__, b)
1115 raise a
1116 except A as e:
1117 exc = e
1118
1119 # Expect A -> C -> B, without cycle
1120 self.assertIs(exc, a)
1121 self.assertIs(a.__context__, c)
1122 self.assertIs(c.__context__, b)
1123 self.assertIsNone(b.__context__)
1124
1125 def test_no_hang_on_context_chain_cycle1(self):
1126 # See issue 25782. Cycle in context chain.
1127
1128 def cycle():
1129 try:
1130 raise ValueError(1)
1131 except ValueError as ex:
1132 ex.__context__ = ex
1133 raise TypeError(2)
1134
1135 try:
1136 cycle()
1137 except Exception as e:
1138 exc = e
1139
1140 self.assertIsInstance(exc, TypeError)
1141 self.assertIsInstance(exc.__context__, ValueError)
1142 self.assertIs(exc.__context__.__context__, exc.__context__)
1143
1144 def test_no_hang_on_context_chain_cycle2(self):
1145 # See issue 25782. Cycle at head of context chain.
1146
1147 class ESC[4;38;5;81mA(ESC[4;38;5;149mException):
1148 pass
1149 class ESC[4;38;5;81mB(ESC[4;38;5;149mException):
1150 pass
1151 class ESC[4;38;5;81mC(ESC[4;38;5;149mException):
1152 pass
1153
1154 # Context cycle:
1155 # +-----------+
1156 # V |
1157 # C --> B --> A
1158 with self.assertRaises(C) as cm:
1159 try:
1160 raise A()
1161 except A as _a:
1162 a = _a
1163 try:
1164 raise B()
1165 except B as _b:
1166 b = _b
1167 try:
1168 raise C()
1169 except C as _c:
1170 c = _c
1171 a.__context__ = c
1172 raise c
1173
1174 self.assertIs(cm.exception, c)
1175 # Verify the expected context chain cycle
1176 self.assertIs(c.__context__, b)
1177 self.assertIs(b.__context__, a)
1178 self.assertIs(a.__context__, c)
1179
1180 def test_no_hang_on_context_chain_cycle3(self):
1181 # See issue 25782. Longer context chain with cycle.
1182
1183 class ESC[4;38;5;81mA(ESC[4;38;5;149mException):
1184 pass
1185 class ESC[4;38;5;81mB(ESC[4;38;5;149mException):
1186 pass
1187 class ESC[4;38;5;81mC(ESC[4;38;5;149mException):
1188 pass
1189 class ESC[4;38;5;81mD(ESC[4;38;5;149mException):
1190 pass
1191 class ESC[4;38;5;81mE(ESC[4;38;5;149mException):
1192 pass
1193
1194 # Context cycle:
1195 # +-----------+
1196 # V |
1197 # E --> D --> C --> B --> A
1198 with self.assertRaises(E) as cm:
1199 try:
1200 raise A()
1201 except A as _a:
1202 a = _a
1203 try:
1204 raise B()
1205 except B as _b:
1206 b = _b
1207 try:
1208 raise C()
1209 except C as _c:
1210 c = _c
1211 a.__context__ = c
1212 try:
1213 raise D()
1214 except D as _d:
1215 d = _d
1216 e = E()
1217 raise e
1218
1219 self.assertIs(cm.exception, e)
1220 # Verify the expected context chain cycle
1221 self.assertIs(e.__context__, d)
1222 self.assertIs(d.__context__, c)
1223 self.assertIs(c.__context__, b)
1224 self.assertIs(b.__context__, a)
1225 self.assertIs(a.__context__, c)
1226
1227 def test_context_of_exception_in_try_and_finally(self):
1228 try:
1229 try:
1230 te = TypeError(1)
1231 raise te
1232 finally:
1233 ve = ValueError(2)
1234 raise ve
1235 except Exception as e:
1236 exc = e
1237
1238 self.assertIs(exc, ve)
1239 self.assertIs(exc.__context__, te)
1240
1241 def test_context_of_exception_in_except_and_finally(self):
1242 try:
1243 try:
1244 te = TypeError(1)
1245 raise te
1246 except:
1247 ve = ValueError(2)
1248 raise ve
1249 finally:
1250 oe = OSError(3)
1251 raise oe
1252 except Exception as e:
1253 exc = e
1254
1255 self.assertIs(exc, oe)
1256 self.assertIs(exc.__context__, ve)
1257 self.assertIs(exc.__context__.__context__, te)
1258
1259 def test_context_of_exception_in_else_and_finally(self):
1260 try:
1261 try:
1262 pass
1263 except:
1264 pass
1265 else:
1266 ve = ValueError(1)
1267 raise ve
1268 finally:
1269 oe = OSError(2)
1270 raise oe
1271 except Exception as e:
1272 exc = e
1273
1274 self.assertIs(exc, oe)
1275 self.assertIs(exc.__context__, ve)
1276
1277 def test_unicode_change_attributes(self):
1278 # See issue 7309. This was a crasher.
1279
1280 u = UnicodeEncodeError('baz', 'xxxxx', 1, 5, 'foo')
1281 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo")
1282 u.end = 2
1283 self.assertEqual(str(u), "'baz' codec can't encode character '\\x78' in position 1: foo")
1284 u.end = 5
1285 u.reason = 0x345345345345345345
1286 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
1287 u.encoding = 4000
1288 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
1289 u.start = 1000
1290 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")
1291
1292 u = UnicodeDecodeError('baz', b'xxxxx', 1, 5, 'foo')
1293 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo")
1294 u.end = 2
1295 self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo")
1296 u.end = 5
1297 u.reason = 0x345345345345345345
1298 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
1299 u.encoding = 4000
1300 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
1301 u.start = 1000
1302 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")
1303
1304 u = UnicodeTranslateError('xxxx', 1, 5, 'foo')
1305 self.assertEqual(str(u), "can't translate characters in position 1-4: foo")
1306 u.end = 2
1307 self.assertEqual(str(u), "can't translate character '\\x78' in position 1: foo")
1308 u.end = 5
1309 u.reason = 0x345345345345345345
1310 self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997")
1311 u.start = 1000
1312 self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")
1313
1314 def test_unicode_errors_no_object(self):
1315 # See issue #21134.
1316 klasses = UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError
1317 for klass in klasses:
1318 self.assertEqual(str(klass.__new__(klass)), "")
1319
1320 @no_tracing
1321 def test_badisinstance(self):
1322 # Bug #2542: if issubclass(e, MyException) raises an exception,
1323 # it should be ignored
1324 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
1325 def __subclasscheck__(cls, subclass):
1326 raise ValueError()
1327 class ESC[4;38;5;81mMyException(ESC[4;38;5;149mException, metaclass=ESC[4;38;5;149mMeta):
1328 pass
1329
1330 with captured_stderr() as stderr:
1331 try:
1332 raise KeyError()
1333 except MyException as e:
1334 self.fail("exception should not be a MyException")
1335 except KeyError:
1336 pass
1337 except:
1338 self.fail("Should have raised KeyError")
1339 else:
1340 self.fail("Should have raised KeyError")
1341
1342 def g():
1343 try:
1344 return g()
1345 except RecursionError as e:
1346 return e
1347 exc = g()
1348 self.assertIsInstance(exc, RecursionError, type(exc))
1349 self.assertIn("maximum recursion depth exceeded", str(exc))
1350
1351
1352 @cpython_only
1353 @support.requires_resource('cpu')
1354 def test_trashcan_recursion(self):
1355 # See bpo-33930
1356
1357 def foo():
1358 o = object()
1359 for x in range(1_000_000):
1360 # Create a big chain of method objects that will trigger
1361 # a deep chain of calls when they need to be destructed.
1362 o = o.__dir__
1363
1364 foo()
1365 support.gc_collect()
1366
1367 @cpython_only
1368 def test_recursion_normalizing_exception(self):
1369 # Issue #22898.
1370 # Test that a RecursionError is raised when tstate->recursion_depth is
1371 # equal to recursion_limit in PyErr_NormalizeException() and check
1372 # that a ResourceWarning is printed.
1373 # Prior to #22898, the recursivity of PyErr_NormalizeException() was
1374 # controlled by tstate->recursion_depth and a PyExc_RecursionErrorInst
1375 # singleton was being used in that case, that held traceback data and
1376 # locals indefinitely and would cause a segfault in _PyExc_Fini() upon
1377 # finalization of these locals.
1378 code = """if 1:
1379 import sys
1380 from _testinternalcapi import get_recursion_depth
1381 from test import support
1382
1383 class MyException(Exception): pass
1384
1385 def setrecursionlimit(depth):
1386 while 1:
1387 try:
1388 sys.setrecursionlimit(depth)
1389 return depth
1390 except RecursionError:
1391 # sys.setrecursionlimit() raises a RecursionError if
1392 # the new recursion limit is too low (issue #25274).
1393 depth += 1
1394
1395 def recurse(cnt):
1396 cnt -= 1
1397 if cnt:
1398 recurse(cnt)
1399 else:
1400 generator.throw(MyException)
1401
1402 def gen():
1403 f = open(%a, mode='rb', buffering=0)
1404 yield
1405
1406 generator = gen()
1407 next(generator)
1408 recursionlimit = sys.getrecursionlimit()
1409 try:
1410 recurse(support.EXCEEDS_RECURSION_LIMIT)
1411 finally:
1412 sys.setrecursionlimit(recursionlimit)
1413 print('Done.')
1414 """ % __file__
1415 rc, out, err = script_helper.assert_python_failure("-Wd", "-c", code)
1416 # Check that the program does not fail with SIGABRT.
1417 self.assertEqual(rc, 1)
1418 self.assertIn(b'RecursionError', err)
1419 self.assertIn(b'ResourceWarning', err)
1420 self.assertIn(b'Done.', out)
1421
1422 @cpython_only
1423 def test_recursion_normalizing_infinite_exception(self):
1424 # Issue #30697. Test that a RecursionError is raised when
1425 # maximum recursion depth has been exceeded when creating
1426 # an exception
1427 code = """if 1:
1428 import _testcapi
1429 try:
1430 raise _testcapi.RecursingInfinitelyError
1431 finally:
1432 print('Done.')
1433 """
1434 rc, out, err = script_helper.assert_python_failure("-c", code)
1435 self.assertEqual(rc, 1)
1436 self.assertIn(b'RecursionError: maximum recursion depth exceeded', err)
1437 self.assertIn(b'Done.', out)
1438
1439
1440 def test_recursion_in_except_handler(self):
1441
1442 def set_relative_recursion_limit(n):
1443 depth = 1
1444 while True:
1445 try:
1446 sys.setrecursionlimit(depth)
1447 except RecursionError:
1448 depth += 1
1449 else:
1450 break
1451 sys.setrecursionlimit(depth+n)
1452
1453 def recurse_in_except():
1454 try:
1455 1/0
1456 except:
1457 recurse_in_except()
1458
1459 def recurse_after_except():
1460 try:
1461 1/0
1462 except:
1463 pass
1464 recurse_after_except()
1465
1466 def recurse_in_body_and_except():
1467 try:
1468 recurse_in_body_and_except()
1469 except:
1470 recurse_in_body_and_except()
1471
1472 recursionlimit = sys.getrecursionlimit()
1473 try:
1474 set_relative_recursion_limit(10)
1475 for func in (recurse_in_except, recurse_after_except, recurse_in_body_and_except):
1476 with self.subTest(func=func):
1477 try:
1478 func()
1479 except RecursionError:
1480 pass
1481 else:
1482 self.fail("Should have raised a RecursionError")
1483 finally:
1484 sys.setrecursionlimit(recursionlimit)
1485
1486
1487 @cpython_only
1488 def test_recursion_normalizing_with_no_memory(self):
1489 # Issue #30697. Test that in the abort that occurs when there is no
1490 # memory left and the size of the Python frames stack is greater than
1491 # the size of the list of preallocated MemoryError instances, the
1492 # Fatal Python error message mentions MemoryError.
1493 code = """if 1:
1494 import _testcapi
1495 class C(): pass
1496 def recurse(cnt):
1497 cnt -= 1
1498 if cnt:
1499 recurse(cnt)
1500 else:
1501 _testcapi.set_nomemory(0)
1502 C()
1503 recurse(16)
1504 """
1505 with SuppressCrashReport():
1506 rc, out, err = script_helper.assert_python_failure("-c", code)
1507 self.assertIn(b'MemoryError', err)
1508
1509 @cpython_only
1510 def test_MemoryError(self):
1511 # PyErr_NoMemory always raises the same exception instance.
1512 # Check that the traceback is not doubled.
1513 import traceback
1514 from _testcapi import raise_memoryerror
1515 def raiseMemError():
1516 try:
1517 raise_memoryerror()
1518 except MemoryError as e:
1519 tb = e.__traceback__
1520 else:
1521 self.fail("Should have raised a MemoryError")
1522 return traceback.format_tb(tb)
1523
1524 tb1 = raiseMemError()
1525 tb2 = raiseMemError()
1526 self.assertEqual(tb1, tb2)
1527
1528 @cpython_only
1529 def test_exception_with_doc(self):
1530 import _testcapi
1531 doc2 = "This is a test docstring."
1532 doc4 = "This is another test docstring."
1533
1534 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
1535 "error1")
1536
1537 # test basic usage of PyErr_NewException
1538 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
1539 self.assertIs(type(error1), type)
1540 self.assertTrue(issubclass(error1, Exception))
1541 self.assertIsNone(error1.__doc__)
1542
1543 # test with given docstring
1544 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
1545 self.assertEqual(error2.__doc__, doc2)
1546
1547 # test with explicit base (without docstring)
1548 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
1549 base=error2)
1550 self.assertTrue(issubclass(error3, error2))
1551
1552 # test with explicit base tuple
1553 class ESC[4;38;5;81mC(ESC[4;38;5;149mobject):
1554 pass
1555 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
1556 (error3, C))
1557 self.assertTrue(issubclass(error4, error3))
1558 self.assertTrue(issubclass(error4, C))
1559 self.assertEqual(error4.__doc__, doc4)
1560
1561 # test with explicit dictionary
1562 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
1563 error4, {'a': 1})
1564 self.assertTrue(issubclass(error5, error4))
1565 self.assertEqual(error5.a, 1)
1566 self.assertEqual(error5.__doc__, "")
1567
1568 @cpython_only
1569 def test_memory_error_cleanup(self):
1570 # Issue #5437: preallocated MemoryError instances should not keep
1571 # traceback objects alive.
1572 from _testcapi import raise_memoryerror
1573 class ESC[4;38;5;81mC:
1574 pass
1575 wr = None
1576 def inner():
1577 nonlocal wr
1578 c = C()
1579 wr = weakref.ref(c)
1580 raise_memoryerror()
1581 # We cannot use assertRaises since it manually deletes the traceback
1582 try:
1583 inner()
1584 except MemoryError as e:
1585 self.assertNotEqual(wr(), None)
1586 else:
1587 self.fail("MemoryError not raised")
1588 gc_collect() # For PyPy or other GCs.
1589 self.assertEqual(wr(), None)
1590
1591 @no_tracing
1592 def test_recursion_error_cleanup(self):
1593 # Same test as above, but with "recursion exceeded" errors
1594 class ESC[4;38;5;81mC:
1595 pass
1596 wr = None
1597 def inner():
1598 nonlocal wr
1599 c = C()
1600 wr = weakref.ref(c)
1601 inner()
1602 # We cannot use assertRaises since it manually deletes the traceback
1603 try:
1604 inner()
1605 except RecursionError as e:
1606 self.assertNotEqual(wr(), None)
1607 else:
1608 self.fail("RecursionError not raised")
1609 gc_collect() # For PyPy or other GCs.
1610 self.assertEqual(wr(), None)
1611
1612 def test_errno_ENOTDIR(self):
1613 # Issue #12802: "not a directory" errors are ENOTDIR even on Windows
1614 with self.assertRaises(OSError) as cm:
1615 os.listdir(__file__)
1616 self.assertEqual(cm.exception.errno, errno.ENOTDIR, cm.exception)
1617
1618 def test_unraisable(self):
1619 # Issue #22836: PyErr_WriteUnraisable() should give sensible reports
1620 class ESC[4;38;5;81mBrokenDel:
1621 def __del__(self):
1622 exc = ValueError("del is broken")
1623 # The following line is included in the traceback report:
1624 raise exc
1625
1626 obj = BrokenDel()
1627 with support.catch_unraisable_exception() as cm:
1628 del obj
1629
1630 gc_collect() # For PyPy or other GCs.
1631 self.assertEqual(cm.unraisable.object, BrokenDel.__del__)
1632 self.assertIsNotNone(cm.unraisable.exc_traceback)
1633
1634 def test_unhandled(self):
1635 # Check for sensible reporting of unhandled exceptions
1636 for exc_type in (ValueError, BrokenStrException):
1637 with self.subTest(exc_type):
1638 try:
1639 exc = exc_type("test message")
1640 # The following line is included in the traceback report:
1641 raise exc
1642 except exc_type:
1643 with captured_stderr() as stderr:
1644 sys.__excepthook__(*sys.exc_info())
1645 report = stderr.getvalue()
1646 self.assertIn("test_exceptions.py", report)
1647 self.assertIn("raise exc", report)
1648 self.assertIn(exc_type.__name__, report)
1649 if exc_type is BrokenStrException:
1650 self.assertIn("<exception str() failed>", report)
1651 else:
1652 self.assertIn("test message", report)
1653 self.assertTrue(report.endswith("\n"))
1654
1655 @cpython_only
1656 def test_memory_error_in_PyErr_PrintEx(self):
1657 code = """if 1:
1658 import _testcapi
1659 class C(): pass
1660 _testcapi.set_nomemory(0, %d)
1661 C()
1662 """
1663
1664 # Issue #30817: Abort in PyErr_PrintEx() when no memory.
1665 # Span a large range of tests as the CPython code always evolves with
1666 # changes that add or remove memory allocations.
1667 for i in range(1, 20):
1668 rc, out, err = script_helper.assert_python_failure("-c", code % i)
1669 self.assertIn(rc, (1, 120))
1670 self.assertIn(b'MemoryError', err)
1671
1672 def test_yield_in_nested_try_excepts(self):
1673 #Issue #25612
1674 class ESC[4;38;5;81mMainError(ESC[4;38;5;149mException):
1675 pass
1676
1677 class ESC[4;38;5;81mSubError(ESC[4;38;5;149mException):
1678 pass
1679
1680 def main():
1681 try:
1682 raise MainError()
1683 except MainError:
1684 try:
1685 yield
1686 except SubError:
1687 pass
1688 raise
1689
1690 coro = main()
1691 coro.send(None)
1692 with self.assertRaises(MainError):
1693 coro.throw(SubError())
1694
1695 def test_generator_doesnt_retain_old_exc2(self):
1696 #Issue 28884#msg282532
1697 def g():
1698 try:
1699 raise ValueError
1700 except ValueError:
1701 yield 1
1702 self.assertIsNone(sys.exception())
1703 yield 2
1704
1705 gen = g()
1706
1707 try:
1708 raise IndexError
1709 except IndexError:
1710 self.assertEqual(next(gen), 1)
1711 self.assertEqual(next(gen), 2)
1712
1713 def test_raise_in_generator(self):
1714 #Issue 25612#msg304117
1715 def g():
1716 yield 1
1717 raise
1718 yield 2
1719
1720 with self.assertRaises(ZeroDivisionError):
1721 i = g()
1722 try:
1723 1/0
1724 except:
1725 next(i)
1726 next(i)
1727
1728 @unittest.skipUnless(__debug__, "Won't work if __debug__ is False")
1729 def test_assert_shadowing(self):
1730 # Shadowing AssertionError would cause the assert statement to
1731 # misbehave.
1732 global AssertionError
1733 AssertionError = TypeError
1734 try:
1735 assert False, 'hello'
1736 except BaseException as e:
1737 del AssertionError
1738 self.assertIsInstance(e, AssertionError)
1739 self.assertEqual(str(e), 'hello')
1740 else:
1741 del AssertionError
1742 self.fail('Expected exception')
1743
1744 def test_memory_error_subclasses(self):
1745 # bpo-41654: MemoryError instances use a freelist of objects that are
1746 # linked using the 'dict' attribute when they are inactive/dead.
1747 # Subclasses of MemoryError should not participate in the freelist
1748 # schema. This test creates a MemoryError object and keeps it alive
1749 # (therefore advancing the freelist) and then it creates and destroys a
1750 # subclass object. Finally, it checks that creating a new MemoryError
1751 # succeeds, proving that the freelist is not corrupted.
1752
1753 class ESC[4;38;5;81mTestException(ESC[4;38;5;149mMemoryError):
1754 pass
1755
1756 try:
1757 raise MemoryError
1758 except MemoryError as exc:
1759 inst = exc
1760
1761 try:
1762 raise TestException
1763 except Exception:
1764 pass
1765
1766 for _ in range(10):
1767 try:
1768 raise MemoryError
1769 except MemoryError as exc:
1770 pass
1771
1772 gc_collect()
1773
1774
1775 class ESC[4;38;5;81mNameErrorTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
1776 def test_name_error_has_name(self):
1777 try:
1778 bluch
1779 except NameError as exc:
1780 self.assertEqual("bluch", exc.name)
1781
1782 def test_issue45826(self):
1783 # regression test for bpo-45826
1784 def f():
1785 with self.assertRaisesRegex(NameError, 'aaa'):
1786 aab
1787
1788 try:
1789 f()
1790 except self.failureException:
1791 with support.captured_stderr() as err:
1792 sys.__excepthook__(*sys.exc_info())
1793
1794 self.assertIn("aab", err.getvalue())
1795
1796 def test_issue45826_focused(self):
1797 def f():
1798 try:
1799 nonsense
1800 except BaseException as E:
1801 E.with_traceback(None)
1802 raise ZeroDivisionError()
1803
1804 try:
1805 f()
1806 except ZeroDivisionError:
1807 with support.captured_stderr() as err:
1808 sys.__excepthook__(*sys.exc_info())
1809
1810 self.assertIn("nonsense", err.getvalue())
1811 self.assertIn("ZeroDivisionError", err.getvalue())
1812
1813 # Note: name suggestion tests live in `test_traceback`.
1814
1815
1816 class ESC[4;38;5;81mAttributeErrorTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
1817 def test_attributes(self):
1818 # Setting 'attr' should not be a problem.
1819 exc = AttributeError('Ouch!')
1820 self.assertIsNone(exc.name)
1821 self.assertIsNone(exc.obj)
1822
1823 sentinel = object()
1824 exc = AttributeError('Ouch', name='carry', obj=sentinel)
1825 self.assertEqual(exc.name, 'carry')
1826 self.assertIs(exc.obj, sentinel)
1827
1828 def test_getattr_has_name_and_obj(self):
1829 class ESC[4;38;5;81mA:
1830 blech = None
1831
1832 obj = A()
1833 try:
1834 obj.bluch
1835 except AttributeError as exc:
1836 self.assertEqual("bluch", exc.name)
1837 self.assertEqual(obj, exc.obj)
1838 try:
1839 object.__getattribute__(obj, "bluch")
1840 except AttributeError as exc:
1841 self.assertEqual("bluch", exc.name)
1842 self.assertEqual(obj, exc.obj)
1843
1844 def test_getattr_has_name_and_obj_for_method(self):
1845 class ESC[4;38;5;81mA:
1846 def blech(self):
1847 return
1848
1849 obj = A()
1850 try:
1851 obj.bluch()
1852 except AttributeError as exc:
1853 self.assertEqual("bluch", exc.name)
1854 self.assertEqual(obj, exc.obj)
1855
1856 # Note: name suggestion tests live in `test_traceback`.
1857
1858
1859 class ESC[4;38;5;81mImportErrorTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
1860
1861 def test_attributes(self):
1862 # Setting 'name' and 'path' should not be a problem.
1863 exc = ImportError('test')
1864 self.assertIsNone(exc.name)
1865 self.assertIsNone(exc.path)
1866
1867 exc = ImportError('test', name='somemodule')
1868 self.assertEqual(exc.name, 'somemodule')
1869 self.assertIsNone(exc.path)
1870
1871 exc = ImportError('test', path='somepath')
1872 self.assertEqual(exc.path, 'somepath')
1873 self.assertIsNone(exc.name)
1874
1875 exc = ImportError('test', path='somepath', name='somename')
1876 self.assertEqual(exc.name, 'somename')
1877 self.assertEqual(exc.path, 'somepath')
1878
1879 msg = "'invalid' is an invalid keyword argument for ImportError"
1880 with self.assertRaisesRegex(TypeError, msg):
1881 ImportError('test', invalid='keyword')
1882
1883 with self.assertRaisesRegex(TypeError, msg):
1884 ImportError('test', name='name', invalid='keyword')
1885
1886 with self.assertRaisesRegex(TypeError, msg):
1887 ImportError('test', path='path', invalid='keyword')
1888
1889 with self.assertRaisesRegex(TypeError, msg):
1890 ImportError(invalid='keyword')
1891
1892 with self.assertRaisesRegex(TypeError, msg):
1893 ImportError('test', invalid='keyword', another=True)
1894
1895 def test_reset_attributes(self):
1896 exc = ImportError('test', name='name', path='path')
1897 self.assertEqual(exc.args, ('test',))
1898 self.assertEqual(exc.msg, 'test')
1899 self.assertEqual(exc.name, 'name')
1900 self.assertEqual(exc.path, 'path')
1901
1902 # Reset not specified attributes
1903 exc.__init__()
1904 self.assertEqual(exc.args, ())
1905 self.assertEqual(exc.msg, None)
1906 self.assertEqual(exc.name, None)
1907 self.assertEqual(exc.path, None)
1908
1909 def test_non_str_argument(self):
1910 # Issue #15778
1911 with check_warnings(('', BytesWarning), quiet=True):
1912 arg = b'abc'
1913 exc = ImportError(arg)
1914 self.assertEqual(str(arg), str(exc))
1915
1916 def test_copy_pickle(self):
1917 for kwargs in (dict(),
1918 dict(name='somename'),
1919 dict(path='somepath'),
1920 dict(name='somename', path='somepath')):
1921 orig = ImportError('test', **kwargs)
1922 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1923 exc = pickle.loads(pickle.dumps(orig, proto))
1924 self.assertEqual(exc.args, ('test',))
1925 self.assertEqual(exc.msg, 'test')
1926 self.assertEqual(exc.name, orig.name)
1927 self.assertEqual(exc.path, orig.path)
1928 for c in copy.copy, copy.deepcopy:
1929 exc = c(orig)
1930 self.assertEqual(exc.args, ('test',))
1931 self.assertEqual(exc.msg, 'test')
1932 self.assertEqual(exc.name, orig.name)
1933 self.assertEqual(exc.path, orig.path)
1934
1935 class ESC[4;38;5;81mSyntaxErrorTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
1936 def test_range_of_offsets(self):
1937 cases = [
1938 # Basic range from 2->7
1939 (("bad.py", 1, 2, "abcdefg", 1, 7),
1940 dedent(
1941 """
1942 File "bad.py", line 1
1943 abcdefg
1944 ^^^^^
1945 SyntaxError: bad bad
1946 """)),
1947 # end_offset = start_offset + 1
1948 (("bad.py", 1, 2, "abcdefg", 1, 3),
1949 dedent(
1950 """
1951 File "bad.py", line 1
1952 abcdefg
1953 ^
1954 SyntaxError: bad bad
1955 """)),
1956 # Negative end offset
1957 (("bad.py", 1, 2, "abcdefg", 1, -2),
1958 dedent(
1959 """
1960 File "bad.py", line 1
1961 abcdefg
1962 ^
1963 SyntaxError: bad bad
1964 """)),
1965 # end offset before starting offset
1966 (("bad.py", 1, 4, "abcdefg", 1, 2),
1967 dedent(
1968 """
1969 File "bad.py", line 1
1970 abcdefg
1971 ^
1972 SyntaxError: bad bad
1973 """)),
1974 # Both offsets negative
1975 (("bad.py", 1, -4, "abcdefg", 1, -2),
1976 dedent(
1977 """
1978 File "bad.py", line 1
1979 abcdefg
1980 SyntaxError: bad bad
1981 """)),
1982 # Both offsets negative and the end more negative
1983 (("bad.py", 1, -4, "abcdefg", 1, -5),
1984 dedent(
1985 """
1986 File "bad.py", line 1
1987 abcdefg
1988 SyntaxError: bad bad
1989 """)),
1990 # Both offsets 0
1991 (("bad.py", 1, 0, "abcdefg", 1, 0),
1992 dedent(
1993 """
1994 File "bad.py", line 1
1995 abcdefg
1996 SyntaxError: bad bad
1997 """)),
1998 # Start offset 0 and end offset not 0
1999 (("bad.py", 1, 0, "abcdefg", 1, 5),
2000 dedent(
2001 """
2002 File "bad.py", line 1
2003 abcdefg
2004 SyntaxError: bad bad
2005 """)),
2006 # End offset pass the source length
2007 (("bad.py", 1, 2, "abcdefg", 1, 100),
2008 dedent(
2009 """
2010 File "bad.py", line 1
2011 abcdefg
2012 ^^^^^^
2013 SyntaxError: bad bad
2014 """)),
2015 ]
2016 for args, expected in cases:
2017 with self.subTest(args=args):
2018 try:
2019 raise SyntaxError("bad bad", args)
2020 except SyntaxError as exc:
2021 with support.captured_stderr() as err:
2022 sys.__excepthook__(*sys.exc_info())
2023 self.assertIn(expected, err.getvalue())
2024 the_exception = exc
2025
2026 def test_encodings(self):
2027 source = (
2028 '# -*- coding: cp437 -*-\n'
2029 '"¢¢¢¢¢¢" + f(4, x for x in range(1))\n'
2030 )
2031 try:
2032 with open(TESTFN, 'w', encoding='cp437') as testfile:
2033 testfile.write(source)
2034 rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN)
2035 err = err.decode('utf-8').splitlines()
2036
2037 self.assertEqual(err[-3], ' "¢¢¢¢¢¢" + f(4, x for x in range(1))')
2038 self.assertEqual(err[-2], ' ^^^^^^^^^^^^^^^^^^^')
2039 finally:
2040 unlink(TESTFN)
2041
2042 # Check backwards tokenizer errors
2043 source = '# -*- coding: ascii -*-\n\n(\n'
2044 try:
2045 with open(TESTFN, 'w', encoding='ascii') as testfile:
2046 testfile.write(source)
2047 rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN)
2048 err = err.decode('utf-8').splitlines()
2049
2050 self.assertEqual(err[-3], ' (')
2051 self.assertEqual(err[-2], ' ^')
2052 finally:
2053 unlink(TESTFN)
2054
2055 def test_non_utf8(self):
2056 # Check non utf-8 characters
2057 try:
2058 with open(TESTFN, 'bw') as testfile:
2059 testfile.write(b"\x89")
2060 rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN)
2061 err = err.decode('utf-8').splitlines()
2062
2063 self.assertIn("SyntaxError: Non-UTF-8 code starting with '\\x89' in file", err[-1])
2064 finally:
2065 unlink(TESTFN)
2066
2067 def test_attributes_new_constructor(self):
2068 args = ("bad.py", 1, 2, "abcdefg", 1, 100)
2069 the_exception = SyntaxError("bad bad", args)
2070 filename, lineno, offset, error, end_lineno, end_offset = args
2071 self.assertEqual(filename, the_exception.filename)
2072 self.assertEqual(lineno, the_exception.lineno)
2073 self.assertEqual(end_lineno, the_exception.end_lineno)
2074 self.assertEqual(offset, the_exception.offset)
2075 self.assertEqual(end_offset, the_exception.end_offset)
2076 self.assertEqual(error, the_exception.text)
2077 self.assertEqual("bad bad", the_exception.msg)
2078
2079 def test_attributes_old_constructor(self):
2080 args = ("bad.py", 1, 2, "abcdefg")
2081 the_exception = SyntaxError("bad bad", args)
2082 filename, lineno, offset, error = args
2083 self.assertEqual(filename, the_exception.filename)
2084 self.assertEqual(lineno, the_exception.lineno)
2085 self.assertEqual(None, the_exception.end_lineno)
2086 self.assertEqual(offset, the_exception.offset)
2087 self.assertEqual(None, the_exception.end_offset)
2088 self.assertEqual(error, the_exception.text)
2089 self.assertEqual("bad bad", the_exception.msg)
2090
2091 def test_incorrect_constructor(self):
2092 args = ("bad.py", 1, 2)
2093 self.assertRaises(TypeError, SyntaxError, "bad bad", args)
2094
2095 args = ("bad.py", 1, 2, 4, 5, 6, 7)
2096 self.assertRaises(TypeError, SyntaxError, "bad bad", args)
2097
2098 args = ("bad.py", 1, 2, "abcdefg", 1)
2099 self.assertRaises(TypeError, SyntaxError, "bad bad", args)
2100
2101
2102 class ESC[4;38;5;81mTestInvalidExceptionMatcher(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
2103 def test_except_star_invalid_exception_type(self):
2104 with self.assertRaises(TypeError):
2105 try:
2106 raise ValueError
2107 except 42:
2108 pass
2109
2110 with self.assertRaises(TypeError):
2111 try:
2112 raise ValueError
2113 except (ValueError, 42):
2114 pass
2115
2116
2117 class ESC[4;38;5;81mPEP626Tests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
2118
2119 def lineno_after_raise(self, f, *expected):
2120 try:
2121 f()
2122 except Exception as ex:
2123 t = ex.__traceback__
2124 else:
2125 self.fail("No exception raised")
2126 lines = []
2127 t = t.tb_next # Skip this function
2128 while t:
2129 frame = t.tb_frame
2130 lines.append(
2131 None if frame.f_lineno is None else
2132 frame.f_lineno-frame.f_code.co_firstlineno
2133 )
2134 t = t.tb_next
2135 self.assertEqual(tuple(lines), expected)
2136
2137 def test_lineno_after_raise_simple(self):
2138 def simple():
2139 1/0
2140 pass
2141 self.lineno_after_raise(simple, 1)
2142
2143 def test_lineno_after_raise_in_except(self):
2144 def in_except():
2145 try:
2146 1/0
2147 except:
2148 1/0
2149 pass
2150 self.lineno_after_raise(in_except, 4)
2151
2152 def test_lineno_after_other_except(self):
2153 def other_except():
2154 try:
2155 1/0
2156 except TypeError as ex:
2157 pass
2158 self.lineno_after_raise(other_except, 3)
2159
2160 def test_lineno_in_named_except(self):
2161 def in_named_except():
2162 try:
2163 1/0
2164 except Exception as ex:
2165 1/0
2166 pass
2167 self.lineno_after_raise(in_named_except, 4)
2168
2169 def test_lineno_in_try(self):
2170 def in_try():
2171 try:
2172 1/0
2173 finally:
2174 pass
2175 self.lineno_after_raise(in_try, 4)
2176
2177 def test_lineno_in_finally_normal(self):
2178 def in_finally_normal():
2179 try:
2180 pass
2181 finally:
2182 1/0
2183 pass
2184 self.lineno_after_raise(in_finally_normal, 4)
2185
2186 def test_lineno_in_finally_except(self):
2187 def in_finally_except():
2188 try:
2189 1/0
2190 finally:
2191 1/0
2192 pass
2193 self.lineno_after_raise(in_finally_except, 4)
2194
2195 def test_lineno_after_with(self):
2196 class ESC[4;38;5;81mNoop:
2197 def __enter__(self):
2198 return self
2199 def __exit__(self, *args):
2200 pass
2201 def after_with():
2202 with Noop():
2203 1/0
2204 pass
2205 self.lineno_after_raise(after_with, 2)
2206
2207 def test_missing_lineno_shows_as_none(self):
2208 def f():
2209 1/0
2210 self.lineno_after_raise(f, 1)
2211 f.__code__ = f.__code__.replace(co_linetable=b'\xf8\xf8\xf8\xf9\xf8\xf8\xf8')
2212 self.lineno_after_raise(f, None)
2213
2214 def test_lineno_after_raise_in_with_exit(self):
2215 class ESC[4;38;5;81mExitFails:
2216 def __enter__(self):
2217 return self
2218 def __exit__(self, *args):
2219 raise ValueError
2220
2221 def after_with():
2222 with ExitFails():
2223 1/0
2224 self.lineno_after_raise(after_with, 1, 1)
2225
2226 if __name__ == '__main__':
2227 unittest.main()