util_test.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # coding: utf-8
  2. from __future__ import absolute_import, division, print_function
  3. import re
  4. import sys
  5. import datetime
  6. import tornado.escape
  7. from tornado.escape import utf8
  8. from tornado.test.util import unittest
  9. from tornado.util import (
  10. raise_exc_info, Configurable, exec_in, ArgReplacer,
  11. timedelta_to_seconds, import_object, re_unescape, is_finalizing, PY3,
  12. )
  13. if PY3:
  14. from io import StringIO
  15. else:
  16. from cStringIO import StringIO
  17. class RaiseExcInfoTest(unittest.TestCase):
  18. def test_two_arg_exception(self):
  19. # This test would fail on python 3 if raise_exc_info were simply
  20. # a three-argument raise statement, because TwoArgException
  21. # doesn't have a "copy constructor"
  22. class TwoArgException(Exception):
  23. def __init__(self, a, b):
  24. super(TwoArgException, self).__init__()
  25. self.a, self.b = a, b
  26. try:
  27. raise TwoArgException(1, 2)
  28. except TwoArgException:
  29. exc_info = sys.exc_info()
  30. try:
  31. raise_exc_info(exc_info)
  32. self.fail("didn't get expected exception")
  33. except TwoArgException as e:
  34. self.assertIs(e, exc_info[1])
  35. class TestConfigurable(Configurable):
  36. @classmethod
  37. def configurable_base(cls):
  38. return TestConfigurable
  39. @classmethod
  40. def configurable_default(cls):
  41. return TestConfig1
  42. class TestConfig1(TestConfigurable):
  43. def initialize(self, pos_arg=None, a=None):
  44. self.a = a
  45. self.pos_arg = pos_arg
  46. class TestConfig2(TestConfigurable):
  47. def initialize(self, pos_arg=None, b=None):
  48. self.b = b
  49. self.pos_arg = pos_arg
  50. class TestConfig3(TestConfigurable):
  51. # TestConfig3 is a configuration option that is itself configurable.
  52. @classmethod
  53. def configurable_base(cls):
  54. return TestConfig3
  55. @classmethod
  56. def configurable_default(cls):
  57. return TestConfig3A
  58. class TestConfig3A(TestConfig3):
  59. def initialize(self, a=None):
  60. self.a = a
  61. class TestConfig3B(TestConfig3):
  62. def initialize(self, b=None):
  63. self.b = b
  64. class ConfigurableTest(unittest.TestCase):
  65. def setUp(self):
  66. self.saved = TestConfigurable._save_configuration()
  67. self.saved3 = TestConfig3._save_configuration()
  68. def tearDown(self):
  69. TestConfigurable._restore_configuration(self.saved)
  70. TestConfig3._restore_configuration(self.saved3)
  71. def checkSubclasses(self):
  72. # no matter how the class is configured, it should always be
  73. # possible to instantiate the subclasses directly
  74. self.assertIsInstance(TestConfig1(), TestConfig1)
  75. self.assertIsInstance(TestConfig2(), TestConfig2)
  76. obj = TestConfig1(a=1)
  77. self.assertEqual(obj.a, 1)
  78. obj = TestConfig2(b=2)
  79. self.assertEqual(obj.b, 2)
  80. def test_default(self):
  81. obj = TestConfigurable()
  82. self.assertIsInstance(obj, TestConfig1)
  83. self.assertIs(obj.a, None)
  84. obj = TestConfigurable(a=1)
  85. self.assertIsInstance(obj, TestConfig1)
  86. self.assertEqual(obj.a, 1)
  87. self.checkSubclasses()
  88. def test_config_class(self):
  89. TestConfigurable.configure(TestConfig2)
  90. obj = TestConfigurable()
  91. self.assertIsInstance(obj, TestConfig2)
  92. self.assertIs(obj.b, None)
  93. obj = TestConfigurable(b=2)
  94. self.assertIsInstance(obj, TestConfig2)
  95. self.assertEqual(obj.b, 2)
  96. self.checkSubclasses()
  97. def test_config_args(self):
  98. TestConfigurable.configure(None, a=3)
  99. obj = TestConfigurable()
  100. self.assertIsInstance(obj, TestConfig1)
  101. self.assertEqual(obj.a, 3)
  102. obj = TestConfigurable(42, a=4)
  103. self.assertIsInstance(obj, TestConfig1)
  104. self.assertEqual(obj.a, 4)
  105. self.assertEqual(obj.pos_arg, 42)
  106. self.checkSubclasses()
  107. # args bound in configure don't apply when using the subclass directly
  108. obj = TestConfig1()
  109. self.assertIs(obj.a, None)
  110. def test_config_class_args(self):
  111. TestConfigurable.configure(TestConfig2, b=5)
  112. obj = TestConfigurable()
  113. self.assertIsInstance(obj, TestConfig2)
  114. self.assertEqual(obj.b, 5)
  115. obj = TestConfigurable(42, b=6)
  116. self.assertIsInstance(obj, TestConfig2)
  117. self.assertEqual(obj.b, 6)
  118. self.assertEqual(obj.pos_arg, 42)
  119. self.checkSubclasses()
  120. # args bound in configure don't apply when using the subclass directly
  121. obj = TestConfig2()
  122. self.assertIs(obj.b, None)
  123. def test_config_multi_level(self):
  124. TestConfigurable.configure(TestConfig3, a=1)
  125. obj = TestConfigurable()
  126. self.assertIsInstance(obj, TestConfig3A)
  127. self.assertEqual(obj.a, 1)
  128. TestConfigurable.configure(TestConfig3)
  129. TestConfig3.configure(TestConfig3B, b=2)
  130. obj = TestConfigurable()
  131. self.assertIsInstance(obj, TestConfig3B)
  132. self.assertEqual(obj.b, 2)
  133. def test_config_inner_level(self):
  134. # The inner level can be used even when the outer level
  135. # doesn't point to it.
  136. obj = TestConfig3()
  137. self.assertIsInstance(obj, TestConfig3A)
  138. TestConfig3.configure(TestConfig3B)
  139. obj = TestConfig3()
  140. self.assertIsInstance(obj, TestConfig3B)
  141. # Configuring the base doesn't configure the inner.
  142. obj = TestConfigurable()
  143. self.assertIsInstance(obj, TestConfig1)
  144. TestConfigurable.configure(TestConfig2)
  145. obj = TestConfigurable()
  146. self.assertIsInstance(obj, TestConfig2)
  147. obj = TestConfig3()
  148. self.assertIsInstance(obj, TestConfig3B)
  149. class UnicodeLiteralTest(unittest.TestCase):
  150. def test_unicode_escapes(self):
  151. self.assertEqual(utf8(u'\u00e9'), b'\xc3\xa9')
  152. class ExecInTest(unittest.TestCase):
  153. # This test is python 2 only because there are no new future imports
  154. # defined in python 3 yet.
  155. @unittest.skipIf(sys.version_info >= print_function.getMandatoryRelease(),
  156. 'no testable future imports')
  157. def test_no_inherit_future(self):
  158. # This file has from __future__ import print_function...
  159. f = StringIO()
  160. print('hello', file=f)
  161. # ...but the template doesn't
  162. exec_in('print >> f, "world"', dict(f=f))
  163. self.assertEqual(f.getvalue(), 'hello\nworld\n')
  164. class ArgReplacerTest(unittest.TestCase):
  165. def setUp(self):
  166. def function(x, y, callback=None, z=None):
  167. pass
  168. self.replacer = ArgReplacer(function, 'callback')
  169. def test_omitted(self):
  170. args = (1, 2)
  171. kwargs = dict()
  172. self.assertIs(self.replacer.get_old_value(args, kwargs), None)
  173. self.assertEqual(self.replacer.replace('new', args, kwargs),
  174. (None, (1, 2), dict(callback='new')))
  175. def test_position(self):
  176. args = (1, 2, 'old', 3)
  177. kwargs = dict()
  178. self.assertEqual(self.replacer.get_old_value(args, kwargs), 'old')
  179. self.assertEqual(self.replacer.replace('new', args, kwargs),
  180. ('old', [1, 2, 'new', 3], dict()))
  181. def test_keyword(self):
  182. args = (1,)
  183. kwargs = dict(y=2, callback='old', z=3)
  184. self.assertEqual(self.replacer.get_old_value(args, kwargs), 'old')
  185. self.assertEqual(self.replacer.replace('new', args, kwargs),
  186. ('old', (1,), dict(y=2, callback='new', z=3)))
  187. class TimedeltaToSecondsTest(unittest.TestCase):
  188. def test_timedelta_to_seconds(self):
  189. time_delta = datetime.timedelta(hours=1)
  190. self.assertEqual(timedelta_to_seconds(time_delta), 3600.0)
  191. class ImportObjectTest(unittest.TestCase):
  192. def test_import_member(self):
  193. self.assertIs(import_object('tornado.escape.utf8'), utf8)
  194. def test_import_member_unicode(self):
  195. self.assertIs(import_object(u'tornado.escape.utf8'), utf8)
  196. def test_import_module(self):
  197. self.assertIs(import_object('tornado.escape'), tornado.escape)
  198. def test_import_module_unicode(self):
  199. # The internal implementation of __import__ differs depending on
  200. # whether the thing being imported is a module or not.
  201. # This variant requires a byte string in python 2.
  202. self.assertIs(import_object(u'tornado.escape'), tornado.escape)
  203. class ReUnescapeTest(unittest.TestCase):
  204. def test_re_unescape(self):
  205. test_strings = (
  206. '/favicon.ico',
  207. 'index.html',
  208. 'Hello, World!',
  209. '!$@#%;',
  210. )
  211. for string in test_strings:
  212. self.assertEqual(string, re_unescape(re.escape(string)))
  213. def test_re_unescape_raises_error_on_invalid_input(self):
  214. with self.assertRaises(ValueError):
  215. re_unescape('\\d')
  216. with self.assertRaises(ValueError):
  217. re_unescape('\\b')
  218. with self.assertRaises(ValueError):
  219. re_unescape('\\Z')
  220. class IsFinalizingTest(unittest.TestCase):
  221. def test_basic(self):
  222. self.assertFalse(is_finalizing())