try:
# Under python2.5, the fake filename used here must match
# the module name used in __name__ below.
+ # The dont_inherit flag prevents template.py's future imports
+ # from being applied to the generated code.
self.compiled = compile(
escape.to_unicode(self.code),
"%s.generated.py" % self.name.replace('.', '_'),
- "exec")
+ "exec", dont_inherit=True)
except Exception:
formatted_code = _format_code(self.code).rstrip()
app_log.error("%s code:\n%s", self.name, formatted_code)
from __future__ import absolute_import, division, print_function, with_statement
import os
+import sys
import traceback
from tornado.escape import utf8, native_str, to_unicode
except ParseError:
pass
+ @unittest.skipIf(sys.version_info >= division.getMandatoryRelease(),
+ 'no testable future imports')
+ def test_no_inherit_future(self):
+ # This file has from __future__ import division...
+ self.assertEqual(1 / 2, 0.5)
+ # ...but the template doesn't
+ template = Template('{{ 1 / 2 }}')
+ self.assertEqual(template.generate(), '0')
+
class StackTraceTest(unittest.TestCase):
def test_error_line_number_expression(self):
import sys
from tornado.escape import utf8
-from tornado.util import raise_exc_info, Configurable, u
+from tornado.util import raise_exc_info, Configurable, u, exec_in
from tornado.test.util import unittest
+try:
+ from cStringIO import StringIO # py2
+except ImportError:
+ from io import StringIO # py3
class RaiseExcInfoTest(unittest.TestCase):
def test_two_arg_exception(self):
class UnicodeLiteralTest(unittest.TestCase):
def test_unicode_escapes(self):
self.assertEqual(utf8(u('\u00e9')), b'\xc3\xa9')
+
+
+class ExecInTest(unittest.TestCase):
+ # This test is python 2 only because there are no new future imports
+ # defined in python 3 yet.
+ @unittest.skipIf(sys.version_info >= print_function.getMandatoryRelease(),
+ 'no testable future imports')
+ def test_no_inherit_future(self):
+ # This file has from __future__ import print_function...
+ f = StringIO()
+ print('hello', file=f)
+ # ...but the template doesn't
+ exec_in('print >> f, "world"', dict(f=f))
+ self.assertEqual(f.getvalue(), 'hello\nworld\n')
basestring_type = basestring
-# 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])
if sys.version_info > (3,):
exec("""
def raise_exc_info(exc_info):
raise exc_info[1].with_traceback(exc_info[2])
def exec_in(code, glob, loc=None):
+ if isinstance(code, str):
+ code = compile(code, '<string>', 'exec', dont_inherit=True)
exec(code, glob, loc)
""")
else:
raise exc_info[0], exc_info[1], exc_info[2]
def exec_in(code, glob, loc=None):
+ if isinstance(code, basestring):
+ # exec(string) inherits the caller's future imports; compile
+ # the string first to prevent that.
+ code = compile(code, '<string>', 'exec', dont_inherit=True)
exec code in glob, loc
""")