Replace all occurrences of 3-argument raise statements with the

version from testing.py, which works better with 2to3.

Closes #508
This commit is contained in:
Ben Darnell 2012-05-10 23:26:34 -07:00
parent 25f4990043
commit a9443b7fdc
6 changed files with 51 additions and 10 deletions

View File

@ -74,6 +74,7 @@ import itertools
import sys
import threading
from tornado.util import raise_exc_info
class _State(threading.local):
def __init__(self):
@ -248,4 +249,4 @@ def _nested(*managers):
# Don't rely on sys.exc_info() still containing
# the right information. Another exception may
# have been raised and caught by an exit method
raise exc[0], exc[1], exc[2]
raise_exc_info(exc)

View File

@ -24,6 +24,7 @@ TEST_MODULES = [
'tornado.test.template_test',
'tornado.test.testing_test',
'tornado.test.twisted_test',
'tornado.test.util_test',
'tornado.test.web_test',
'tornado.test.wsgi_test',
]

25
tornado/test/util_test.py Normal file
View File

@ -0,0 +1,25 @@
from __future__ import absolute_import, division, with_statement
import sys
import unittest
from tornado.util import raise_exc_info
class RaiseExcInfoTest(unittest.TestCase):
def test_two_arg_exception(self):
# This test would fail on python 3 if raise_exc_info were simply
# a three-argument raise statement, because TwoArgException
# doesn't have a "copy constructor"
class TwoArgException(Exception):
def __init__(self, a, b):
super(TwoArgException, self).__init__()
self.a, self.b = a, b
try:
raise TwoArgException(1, 2)
except TwoArgException:
exc_info = sys.exc_info()
try:
raise_exc_info(exc_info)
self.fail("didn't get expected exception")
except TwoArgException, e:
self.assertTrue(e is exc_info[1])

View File

@ -32,6 +32,7 @@ except ImportError:
HTTPServer = None
IOLoop = None
from tornado.stack_context import StackContext, NullContext
from tornado.util import raise_exc_info
import contextlib
import logging
import signal
@ -142,12 +143,7 @@ class AsyncTestCase(unittest.TestCase):
if self.__failure is not None:
failure = self.__failure
self.__failure = None
# 2to3 isn't smart enough to convert three-argument raise
# statements correctly in some cases.
if isinstance(failure[1], failure[0]):
raise failure[1], None, failure[2]
else:
raise failure[0], failure[1], failure[2]
raise_exc_info(failure)
def run(self, result=None):

View File

@ -46,6 +46,24 @@ else:
bytes_type = str
def raise_exc_info(exc_info):
"""Re-raise an exception (with original traceback) from an exc_info tuple.
The argument is a ``(type, value, traceback)`` tuple as returned by
`sys.exc_info`.
"""
# 2to3 isn't smart enough to convert three-argument raise
# statements correctly in some cases.
if isinstance(exc_info[1], exc_info[0]):
raise exc_info[1], None, exc_info[2]
# After 2to3: raise exc_info[1].with_traceback(exc_info[2])
else:
# I think this branch is only taken for string exceptions,
# which were removed in Python 2.6.
raise exc_info[0], exc_info[1], exc_info[2]
# After 2to3: raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
def doctests():
import doctest
return doctest.DocTestSuite()

View File

@ -83,7 +83,7 @@ from tornado import locale
from tornado import stack_context
from tornado import template
from tornado.escape import utf8, _unicode
from tornado.util import b, bytes_type, import_object, ObjectDict
from tornado.util import b, bytes_type, import_object, ObjectDict, raise_exc_info
try:
from io import BytesIO # python 3
@ -739,7 +739,7 @@ class RequestHandler(object):
kwargs['exception'] = exc_info[1]
try:
# Put the traceback into sys.exc_info()
raise exc_info[0], exc_info[1], exc_info[2]
raise_exc_info(exc_info)
except Exception:
self.finish(self.get_error_html(status_code, **kwargs))
else:
@ -984,7 +984,7 @@ class RequestHandler(object):
# the exception value instead of the full triple,
# so re-raise the exception to ensure that it's in
# sys.exc_info()
raise type, value, traceback
raise_exc_info((type, value, traceback))
except Exception:
self._handle_request_exception(value)
return True