except ImportError:
futures = None
+try:
+ import typing
+except ImportError:
+ typing = None
+
# Can the garbage collector handle cycles that include __del__ methods?
# This is true in cpython beginning with version 3.4 (PEP 442).
TracebackFuture = Future
if futures is None:
- FUTURES = Future
+ FUTURES = Future # type: typing.Union[type, typing.Tuple[type, ...]]
else:
FUTURES = (futures.Future, Future)
from __future__ import absolute_import, division, print_function, with_statement
+import json
import re
import sys
-from tornado.util import unicode_type, basestring_type
-
-try:
- from urllib.parse import parse_qs as _parse_qs # py3
-except ImportError:
- from urlparse import parse_qs as _parse_qs # Python 2.6+
-
-try:
- import htmlentitydefs # py2
-except ImportError:
- import html.entities as htmlentitydefs # py3
-
-try:
- import urllib.parse as urllib_parse # py3
-except ImportError:
- import urllib as urllib_parse # py2
+from tornado.util import PY3, unicode_type, basestring_type
-import json
-
-try:
- unichr
-except NameError:
+if PY3:
+ from urllib.parse import parse_qs as _parse_qs
+ import html.entities as htmlentitydefs
+ import urllib.parse as urllib_parse
unichr = chr
+else:
+ from urlparse import parse_qs as _parse_qs
+ import htmlentitydefs
+ import urllib as urllib_parse
+
_XHTML_ESCAPE_RE = re.compile('[&<>"\']')
_XHTML_ESCAPE_DICT = {'&': '&', '<': '<', '>': '>', '"': '"',
# python 3 changed things around enough that we need two separate
# implementations of url_unescape. We also need our own implementation
# of parse_qs since python 3's version insists on decoding everything.
-if sys.version_info[0] < 3:
+if not PY3:
def url_unescape(value, encoding='utf-8', plus=True):
"""Decodes the given value from a URL.
from tornado.ioloop import IOLoop
from tornado.log import app_log
from tornado import stack_context
-from tornado.util import raise_exc_info
+from tornado.util import PY3, raise_exc_info
try:
try:
def isawaitable(x):
return False
-try:
- import builtins # py3
-except ImportError:
+if PY3:
+ import builtins
+else:
import __builtin__ as builtins
from tornado.concurrent import TracebackFuture, is_future
from tornado.log import app_log, gen_log
+from tornado.platform.auto import set_close_exec, Waker
from tornado import stack_context
-from tornado.util import Configurable, errno_from_exception, timedelta_to_seconds
+from tornado.util import PY3, Configurable, errno_from_exception, timedelta_to_seconds
try:
import signal
except ImportError:
signal = None
-try:
- import thread # py2
-except ImportError:
- import _thread as thread # py3
-from tornado.platform.auto import set_close_exec, Waker
+if PY3:
+ import _thread as thread
+else:
+ import thread
_POLL_TIMEOUT = 3600.0
and `tornado.options.parse_config_file`.
"""
if options is None:
- from tornado.options import options
+ import tornado.options
+ options = tornado.options.options
if options.logging is None or options.logging.lower() == 'none':
return
if logger is None:
"""
if options is None:
# late import to prevent cycle
- from tornado.options import options
+ import tornado.options
+ options = tornado.options.options
options.define("logging", default="info",
help=("Set the Python log level. If 'none', tornado won't touch the "
"logging configuration."),
from tornado.concurrent import dummy_executor, run_on_executor
from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
-from tornado.util import Configurable, errno_from_exception
+from tornado.util import PY3, Configurable, errno_from_exception
try:
import ssl
else:
raise
-try:
- xrange # py2
-except NameError:
- xrange = range # py3
+if PY3:
+ xrange = range
if hasattr(ssl, 'match_hostname') and hasattr(ssl, 'CertificateError'): # python 3.2+
ssl_match_hostname = ssl.match_hostname
--- /dev/null
+# auto.py is full of patterns mypy doesn't like, so for type checking
+# purposes we replace it with interface.py.
+
+from .interface import *
--- /dev/null
+def websocket_mask(mask: bytes, data: bytes) -> bytes: ...
import sys
import zlib
+PY3 = sys.version_info >= (3,)
-try:
- xrange # py2
-except NameError:
- xrange = range # py3
+if PY3:
+ xrange = range
# inspect.getargspec() raises DeprecationWarnings in Python 3.5.
# The two functions have compatible interfaces for the parts we need.
-try:
- from inspect import getfullargspec as getargspec # py3
-except ImportError:
- from inspect import getargspec # py2
+if PY3:
+ from inspect import getfullargspec as getargspec
+else:
+ from inspect import getargspec
+
+# Aliases for types that are spelled differently in different Python
+# versions. bytes_type is deprecated and no longer used in Tornado
+# itself but is left in case anyone outside Tornado is using it.
+unicode_type = type(u'')
+bytes_type = bytes
+if PY3:
+ basestring_type = str
+else:
+ # The name basestring doesn't exist in py3 so silence flake8.
+ basestring_type = basestring # noqa
class ObjectDict(dict):
return self.decompressobj.flush()
-if not isinstance(b'', type('')):
- unicode_type = str
- basestring_type = str
-else:
- # These names don't exist in py3, so use noqa comments to disable
- # warnings in flake8.
- unicode_type = unicode # noqa
- basestring_type = basestring # noqa
-
-
def import_object(name):
"""Imports an object by name.
raise ImportError("No module named %s" % parts[-1])
-# Deprecated alias that was used before we dropped py25 support.
-# Left here in case anyone outside Tornado is using it.
-bytes_type = bytes
+# Stubs to make mypy happy (and later for actual type-checking).
+def raise_exc_info(exc_info):
+ pass
+
+
+def exec_in(code, glob, loc=None):
+ pass
+
-if sys.version_info > (3,):
+if PY3:
exec("""
def raise_exc_info(exc_info):
raise exc_info[1].with_traceback(exc_info[2])
`configurable_base` and `configurable_default`, and use the instance
method `initialize` instead of ``__init__``.
"""
- __impl_class = None
- __impl_kwargs = None
+ __impl_class = None # type: type
+ __impl_kwargs = None # type: dict
def __new__(cls, *args, **kwargs):
base = cls.configurable_base()