summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-12-05 09:18:30 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-12-05 09:18:30 (GMT)
commit9d279b87d81b7cd9471e8373d022451bb00f094f (patch)
tree845d27846df2e3be00de264b2d156691b8be38cd
parent02d37d5dd2cefced3e2d834d453d6a5c848a2b9e (diff)
parent969175091c4556e5b7e128ba91ae39f0b80153af (diff)
downloadcpython-9d279b87d81b7cd9471e8373d022451bb00f094f.zip
cpython-9d279b87d81b7cd9471e8373d022451bb00f094f.tar.gz
cpython-9d279b87d81b7cd9471e8373d022451bb00f094f.tar.bz2
(Merge 3.4) Issue #22599: Enhance tokenize.open() to be able to call it during
Python finalization. Before the module kept a reference to the builtins module, but the module attributes are cleared during Python finalization. Instead, keep directly a reference to the open() function. This enhancement is not perfect, calling tokenize.open() can still fail if called very late during Python finalization. Usually, the function is called by the linecache module which is called to display a traceback or emit a warning.
-rw-r--r--Lib/test/test_traceback.py33
-rw-r--r--Lib/tokenize.py7
2 files changed, 37 insertions, 3 deletions
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index e3b28bd..6bd6fa6 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 742abd1..51da484 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>"