util.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. """Miscellaneous utility functions and classes.
  2. This module is used internally by Tornado. It is not necessarily expected
  3. that the functions and classes defined here will be useful to other
  4. applications, but they are documented here in case they are.
  5. The one public-facing part of this module is the `Configurable` class
  6. and its `~Configurable.configure` method, which becomes a part of the
  7. interface of its subclasses, including `.AsyncHTTPClient`, `.IOLoop`,
  8. and `.Resolver`.
  9. """
  10. from __future__ import absolute_import, division, print_function
  11. import array
  12. import atexit
  13. import os
  14. import re
  15. import sys
  16. import zlib
  17. PY3 = sys.version_info >= (3,)
  18. if PY3:
  19. xrange = range
  20. # inspect.getargspec() raises DeprecationWarnings in Python 3.5.
  21. # The two functions have compatible interfaces for the parts we need.
  22. if PY3:
  23. from inspect import getfullargspec as getargspec
  24. else:
  25. from inspect import getargspec
  26. # Aliases for types that are spelled differently in different Python
  27. # versions. bytes_type is deprecated and no longer used in Tornado
  28. # itself but is left in case anyone outside Tornado is using it.
  29. bytes_type = bytes
  30. if PY3:
  31. unicode_type = str
  32. basestring_type = str
  33. else:
  34. # The names unicode and basestring don't exist in py3 so silence flake8.
  35. unicode_type = unicode # noqa
  36. basestring_type = basestring # noqa
  37. try:
  38. import typing # noqa
  39. from typing import cast
  40. _ObjectDictBase = typing.Dict[str, typing.Any]
  41. except ImportError:
  42. _ObjectDictBase = dict
  43. def cast(typ, x):
  44. return x
  45. else:
  46. # More imports that are only needed in type comments.
  47. import datetime # noqa
  48. import types # noqa
  49. from typing import Any, AnyStr, Union, Optional, Dict, Mapping # noqa
  50. from typing import Tuple, Match, Callable # noqa
  51. if PY3:
  52. _BaseString = str
  53. else:
  54. _BaseString = Union[bytes, unicode_type]
  55. try:
  56. from sys import is_finalizing
  57. except ImportError:
  58. # Emulate it
  59. def _get_emulated_is_finalizing():
  60. L = []
  61. atexit.register(lambda: L.append(None))
  62. def is_finalizing():
  63. # Not referencing any globals here
  64. return L != []
  65. return is_finalizing
  66. is_finalizing = _get_emulated_is_finalizing()
  67. class TimeoutError(Exception):
  68. """Exception raised by `.with_timeout` and `.IOLoop.run_sync`.
  69. .. versionchanged:: 5.0:
  70. Unified ``tornado.gen.TimeoutError`` and
  71. ``tornado.ioloop.TimeoutError`` as ``tornado.util.TimeoutError``.
  72. Both former names remain as aliases.
  73. """
  74. class ObjectDict(_ObjectDictBase):
  75. """Makes a dictionary behave like an object, with attribute-style access.
  76. """
  77. def __getattr__(self, name):
  78. # type: (str) -> Any
  79. try:
  80. return self[name]
  81. except KeyError:
  82. raise AttributeError(name)
  83. def __setattr__(self, name, value):
  84. # type: (str, Any) -> None
  85. self[name] = value
  86. class GzipDecompressor(object):
  87. """Streaming gzip decompressor.
  88. The interface is like that of `zlib.decompressobj` (without some of the
  89. optional arguments, but it understands gzip headers and checksums.
  90. """
  91. def __init__(self):
  92. # Magic parameter makes zlib module understand gzip header
  93. # http://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib
  94. # This works on cpython and pypy, but not jython.
  95. self.decompressobj = zlib.decompressobj(16 + zlib.MAX_WBITS)
  96. def decompress(self, value, max_length=None):
  97. # type: (bytes, Optional[int]) -> bytes
  98. """Decompress a chunk, returning newly-available data.
  99. Some data may be buffered for later processing; `flush` must
  100. be called when there is no more input data to ensure that
  101. all data was processed.
  102. If ``max_length`` is given, some input data may be left over
  103. in ``unconsumed_tail``; you must retrieve this value and pass
  104. it back to a future call to `decompress` if it is not empty.
  105. """
  106. return self.decompressobj.decompress(value, max_length)
  107. @property
  108. def unconsumed_tail(self):
  109. # type: () -> bytes
  110. """Returns the unconsumed portion left over
  111. """
  112. return self.decompressobj.unconsumed_tail
  113. def flush(self):
  114. # type: () -> bytes
  115. """Return any remaining buffered data not yet returned by decompress.
  116. Also checks for errors such as truncated input.
  117. No other methods may be called on this object after `flush`.
  118. """
  119. return self.decompressobj.flush()
  120. def import_object(name):
  121. # type: (_BaseString) -> Any
  122. """Imports an object by name.
  123. import_object('x') is equivalent to 'import x'.
  124. import_object('x.y.z') is equivalent to 'from x.y import z'.
  125. >>> import tornado.escape
  126. >>> import_object('tornado.escape') is tornado.escape
  127. True
  128. >>> import_object('tornado.escape.utf8') is tornado.escape.utf8
  129. True
  130. >>> import_object('tornado') is tornado
  131. True
  132. >>> import_object('tornado.missing_module')
  133. Traceback (most recent call last):
  134. ...
  135. ImportError: No module named missing_module
  136. """
  137. if not isinstance(name, str):
  138. # on python 2 a byte string is required.
  139. name = name.encode('utf-8')
  140. if name.count('.') == 0:
  141. return __import__(name, None, None)
  142. parts = name.split('.')
  143. obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
  144. try:
  145. return getattr(obj, parts[-1])
  146. except AttributeError:
  147. raise ImportError("No module named %s" % parts[-1])
  148. # Stubs to make mypy happy (and later for actual type-checking).
  149. def raise_exc_info(exc_info):
  150. # type: (Tuple[type, BaseException, types.TracebackType]) -> None
  151. pass
  152. def exec_in(code, glob, loc=None):
  153. # type: (Any, Dict[str, Any], Optional[Mapping[str, Any]]) -> Any
  154. if isinstance(code, basestring_type):
  155. # exec(string) inherits the caller's future imports; compile
  156. # the string first to prevent that.
  157. code = compile(code, '<string>', 'exec', dont_inherit=True)
  158. exec(code, glob, loc)
  159. if PY3:
  160. exec("""
  161. def raise_exc_info(exc_info):
  162. try:
  163. raise exc_info[1].with_traceback(exc_info[2])
  164. finally:
  165. exc_info = None
  166. """)
  167. else:
  168. exec("""
  169. def raise_exc_info(exc_info):
  170. raise exc_info[0], exc_info[1], exc_info[2]
  171. """)
  172. def errno_from_exception(e):
  173. # type: (BaseException) -> Optional[int]
  174. """Provides the errno from an Exception object.
  175. There are cases that the errno attribute was not set so we pull
  176. the errno out of the args but if someone instantiates an Exception
  177. without any args you will get a tuple error. So this function
  178. abstracts all that behavior to give you a safe way to get the
  179. errno.
  180. """
  181. if hasattr(e, 'errno'):
  182. return e.errno # type: ignore
  183. elif e.args:
  184. return e.args[0]
  185. else:
  186. return None
  187. _alphanum = frozenset(
  188. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
  189. def _re_unescape_replacement(match):
  190. # type: (Match[str]) -> str
  191. group = match.group(1)
  192. if group[0] in _alphanum:
  193. raise ValueError("cannot unescape '\\\\%s'" % group[0])
  194. return group
  195. _re_unescape_pattern = re.compile(r'\\(.)', re.DOTALL)
  196. def re_unescape(s):
  197. # type: (str) -> str
  198. """Unescape a string escaped by `re.escape`.
  199. May raise ``ValueError`` for regular expressions which could not
  200. have been produced by `re.escape` (for example, strings containing
  201. ``\d`` cannot be unescaped).
  202. .. versionadded:: 4.4
  203. """
  204. return _re_unescape_pattern.sub(_re_unescape_replacement, s)
  205. class Configurable(object):
  206. """Base class for configurable interfaces.
  207. A configurable interface is an (abstract) class whose constructor
  208. acts as a factory function for one of its implementation subclasses.
  209. The implementation subclass as well as optional keyword arguments to
  210. its initializer can be set globally at runtime with `configure`.
  211. By using the constructor as the factory method, the interface
  212. looks like a normal class, `isinstance` works as usual, etc. This
  213. pattern is most useful when the choice of implementation is likely
  214. to be a global decision (e.g. when `~select.epoll` is available,
  215. always use it instead of `~select.select`), or when a
  216. previously-monolithic class has been split into specialized
  217. subclasses.
  218. Configurable subclasses must define the class methods
  219. `configurable_base` and `configurable_default`, and use the instance
  220. method `initialize` instead of ``__init__``.
  221. .. versionchanged:: 5.0
  222. It is now possible for configuration to be specified at
  223. multiple levels of a class hierarchy.
  224. """
  225. __impl_class = None # type: type
  226. __impl_kwargs = None # type: Dict[str, Any]
  227. def __new__(cls, *args, **kwargs):
  228. base = cls.configurable_base()
  229. init_kwargs = {}
  230. if cls is base:
  231. impl = cls.configured_class()
  232. if base.__impl_kwargs:
  233. init_kwargs.update(base.__impl_kwargs)
  234. else:
  235. impl = cls
  236. init_kwargs.update(kwargs)
  237. if impl.configurable_base() is not base:
  238. # The impl class is itself configurable, so recurse.
  239. return impl(*args, **init_kwargs)
  240. instance = super(Configurable, cls).__new__(impl)
  241. # initialize vs __init__ chosen for compatibility with AsyncHTTPClient
  242. # singleton magic. If we get rid of that we can switch to __init__
  243. # here too.
  244. instance.initialize(*args, **init_kwargs)
  245. return instance
  246. @classmethod
  247. def configurable_base(cls):
  248. # type: () -> Any
  249. # TODO: This class needs https://github.com/python/typing/issues/107
  250. # to be fully typeable.
  251. """Returns the base class of a configurable hierarchy.
  252. This will normally return the class in which it is defined.
  253. (which is *not* necessarily the same as the cls classmethod parameter).
  254. """
  255. raise NotImplementedError()
  256. @classmethod
  257. def configurable_default(cls):
  258. # type: () -> type
  259. """Returns the implementation class to be used if none is configured."""
  260. raise NotImplementedError()
  261. def initialize(self):
  262. # type: () -> None
  263. """Initialize a `Configurable` subclass instance.
  264. Configurable classes should use `initialize` instead of ``__init__``.
  265. .. versionchanged:: 4.2
  266. Now accepts positional arguments in addition to keyword arguments.
  267. """
  268. @classmethod
  269. def configure(cls, impl, **kwargs):
  270. # type: (Any, **Any) -> None
  271. """Sets the class to use when the base class is instantiated.
  272. Keyword arguments will be saved and added to the arguments passed
  273. to the constructor. This can be used to set global defaults for
  274. some parameters.
  275. """
  276. base = cls.configurable_base()
  277. if isinstance(impl, (str, unicode_type)):
  278. impl = import_object(impl)
  279. if impl is not None and not issubclass(impl, cls):
  280. raise ValueError("Invalid subclass of %s" % cls)
  281. base.__impl_class = impl
  282. base.__impl_kwargs = kwargs
  283. @classmethod
  284. def configured_class(cls):
  285. # type: () -> type
  286. """Returns the currently configured class."""
  287. base = cls.configurable_base()
  288. # Manually mangle the private name to see whether this base
  289. # has been configured (and not another base higher in the
  290. # hierarchy).
  291. if base.__dict__.get('_Configurable__impl_class') is None:
  292. base.__impl_class = cls.configurable_default()
  293. return base.__impl_class
  294. @classmethod
  295. def _save_configuration(cls):
  296. # type: () -> Tuple[type, Dict[str, Any]]
  297. base = cls.configurable_base()
  298. return (base.__impl_class, base.__impl_kwargs)
  299. @classmethod
  300. def _restore_configuration(cls, saved):
  301. # type: (Tuple[type, Dict[str, Any]]) -> None
  302. base = cls.configurable_base()
  303. base.__impl_class = saved[0]
  304. base.__impl_kwargs = saved[1]
  305. class ArgReplacer(object):
  306. """Replaces one value in an ``args, kwargs`` pair.
  307. Inspects the function signature to find an argument by name
  308. whether it is passed by position or keyword. For use in decorators
  309. and similar wrappers.
  310. """
  311. def __init__(self, func, name):
  312. # type: (Callable, str) -> None
  313. self.name = name
  314. try:
  315. self.arg_pos = self._getargnames(func).index(name)
  316. except ValueError:
  317. # Not a positional parameter
  318. self.arg_pos = None
  319. def _getargnames(self, func):
  320. # type: (Callable) -> List[str]
  321. try:
  322. return getargspec(func).args
  323. except TypeError:
  324. if hasattr(func, 'func_code'):
  325. # Cython-generated code has all the attributes needed
  326. # by inspect.getargspec, but the inspect module only
  327. # works with ordinary functions. Inline the portion of
  328. # getargspec that we need here. Note that for static
  329. # functions the @cython.binding(True) decorator must
  330. # be used (for methods it works out of the box).
  331. code = func.func_code # type: ignore
  332. return code.co_varnames[:code.co_argcount]
  333. raise
  334. def get_old_value(self, args, kwargs, default=None):
  335. # type: (List[Any], Dict[str, Any], Any) -> Any
  336. """Returns the old value of the named argument without replacing it.
  337. Returns ``default`` if the argument is not present.
  338. """
  339. if self.arg_pos is not None and len(args) > self.arg_pos:
  340. return args[self.arg_pos]
  341. else:
  342. return kwargs.get(self.name, default)
  343. def replace(self, new_value, args, kwargs):
  344. # type: (Any, List[Any], Dict[str, Any]) -> Tuple[Any, List[Any], Dict[str, Any]]
  345. """Replace the named argument in ``args, kwargs`` with ``new_value``.
  346. Returns ``(old_value, args, kwargs)``. The returned ``args`` and
  347. ``kwargs`` objects may not be the same as the input objects, or
  348. the input objects may be mutated.
  349. If the named argument was not found, ``new_value`` will be added
  350. to ``kwargs`` and None will be returned as ``old_value``.
  351. """
  352. if self.arg_pos is not None and len(args) > self.arg_pos:
  353. # The arg to replace is passed positionally
  354. old_value = args[self.arg_pos]
  355. args = list(args) # *args is normally a tuple
  356. args[self.arg_pos] = new_value
  357. else:
  358. # The arg to replace is either omitted or passed by keyword.
  359. old_value = kwargs.get(self.name)
  360. kwargs[self.name] = new_value
  361. return old_value, args, kwargs
  362. def timedelta_to_seconds(td):
  363. # type: (datetime.timedelta) -> float
  364. """Equivalent to td.total_seconds() (introduced in python 2.7)."""
  365. return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / float(10 ** 6)
  366. def _websocket_mask_python(mask, data):
  367. # type: (bytes, bytes) -> bytes
  368. """Websocket masking function.
  369. `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.
  370. Returns a `bytes` object of the same length as `data` with the mask applied
  371. as specified in section 5.3 of RFC 6455.
  372. This pure-python implementation may be replaced by an optimized version when available.
  373. """
  374. mask_arr = array.array("B", mask)
  375. unmasked_arr = array.array("B", data)
  376. for i in xrange(len(data)):
  377. unmasked_arr[i] = unmasked_arr[i] ^ mask_arr[i % 4]
  378. if PY3:
  379. # tostring was deprecated in py32. It hasn't been removed,
  380. # but since we turn on deprecation warnings in our tests
  381. # we need to use the right one.
  382. return unmasked_arr.tobytes()
  383. else:
  384. return unmasked_arr.tostring()
  385. if (os.environ.get('TORNADO_NO_EXTENSION') or
  386. os.environ.get('TORNADO_EXTENSION') == '0'):
  387. # These environment variables exist to make it easier to do performance
  388. # comparisons; they are not guaranteed to remain supported in the future.
  389. _websocket_mask = _websocket_mask_python
  390. else:
  391. try:
  392. from tornado.speedups import websocket_mask as _websocket_mask
  393. except ImportError:
  394. if os.environ.get('TORNADO_EXTENSION') == '1':
  395. raise
  396. _websocket_mask = _websocket_mask_python
  397. def doctests():
  398. import doctest
  399. return doctest.DocTestSuite()