diff options
-rw-r--r-- | Lib/test/test_traceback.py | 33 | ||||
-rw-r--r-- | Lib/tokenize.py | 7 |
2 files changed, 37 insertions, 3 deletions
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index e3b28bd5515..6bd6fa63033 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -6,6 +6,8 @@ import unittest import re from test.support import run_unittest, Error, captured_output from test.support import TESTFN, unlink, cpython_only +from test.script_helper import assert_python_ok +import textwrap import traceback @@ -169,6 +171,37 @@ class SyntaxTracebackCases(unittest.TestCase): # Issue #18960: coding spec should has no effect do_test("0\n# coding: GBK\n", "h\xe9 ho", 'utf-8', 5) + def test_print_traceback_at_exit(self): + # Issue #22599: Ensure that it is possible to use the traceback module + # to display an exception at Python exit + code = textwrap.dedent(""" + import sys + import traceback + + class PrintExceptionAtExit(object): + def __init__(self): + try: + x = 1 / 0 + except Exception: + self.exc_info = sys.exc_info() + # self.exc_info[1] (traceback) contains frames: + # explicitly clear the reference to self in the current + # frame to break a reference cycle + self = None + + def __del__(self): + traceback.print_exception(*self.exc_info) + + # Keep a reference in the module namespace to call the destructor + # when the module is unloaded + obj = PrintExceptionAtExit() + """) + rc, stdout, stderr = assert_python_ok('-c', code) + expected = [b'Traceback (most recent call last):', + b' File "<string>", line 8, in __init__', + b'ZeroDivisionError: division by zero'] + self.assertEqual(stderr.splitlines(), expected) + class TracebackFormatTests(unittest.TestCase): diff --git a/Lib/tokenize.py b/Lib/tokenize.py index 742abd19922..51da4847f27 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -24,7 +24,6 @@ __author__ = 'Ka-Ping Yee <ping@lfw.org>' __credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, ' 'Skip Montanaro, Raymond Hettinger, Trent Nelson, ' 'Michael Foord') -import builtins from codecs import lookup, BOM_UTF8 import collections from io import TextIOWrapper @@ -431,11 +430,13 @@ def detect_encoding(readline): return default, [first, second] +_builtin_open = open + def open(filename): """Open a file in read only mode using the encoding detected by detect_encoding(). """ - buffer = builtins.open(filename, 'rb') + buffer = _builtin_open(filename, 'rb') encoding, lines = detect_encoding(buffer.readline) buffer.seek(0) text = TextIOWrapper(buffer, encoding, line_buffering=True) @@ -658,7 +659,7 @@ def main(): # Tokenize the input if args.filename: filename = args.filename - with builtins.open(filename, 'rb') as f: + with _builtin_open(filename, 'rb') as f: tokens = list(tokenize(f.readline)) else: filename = "<stdin>" |