Update library: tornado
This commit is contained in:
@@ -25,5 +25,5 @@ from __future__ import absolute_import, division, print_function, with_statement
|
||||
# is zero for an official release, positive for a development branch,
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
version = "3.2b1"
|
||||
version_info = (3, 2, 0, -98)
|
||||
version = "3.2"
|
||||
version_info = (3, 2, 0, 0)
|
||||
|
||||
@@ -36,7 +36,6 @@ Example usage for Google OpenID::
|
||||
|
||||
class GoogleLoginHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.GoogleMixin):
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("openid.mode", None):
|
||||
@@ -607,7 +606,6 @@ class TwitterMixin(OAuthMixin):
|
||||
|
||||
class TwitterLoginHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.TwitterMixin):
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("oauth_token", None):
|
||||
@@ -669,7 +667,6 @@ class TwitterMixin(OAuthMixin):
|
||||
class MainHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.TwitterMixin):
|
||||
@tornado.web.authenticated
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
new_entry = yield self.twitter_request(
|
||||
@@ -748,7 +745,6 @@ class FriendFeedMixin(OAuthMixin):
|
||||
|
||||
class FriendFeedLoginHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.FriendFeedMixin):
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("oauth_token", None):
|
||||
@@ -793,7 +789,6 @@ class FriendFeedMixin(OAuthMixin):
|
||||
class MainHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.FriendFeedMixin):
|
||||
@tornado.web.authenticated
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
new_entry = yield self.friendfeed_request(
|
||||
@@ -877,7 +872,6 @@ class GoogleMixin(OpenIdMixin, OAuthMixin):
|
||||
|
||||
class GoogleLoginHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.GoogleMixin):
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("openid.mode", None):
|
||||
@@ -949,7 +943,10 @@ class GoogleMixin(OpenIdMixin, OAuthMixin):
|
||||
|
||||
|
||||
class GoogleOAuth2Mixin(OAuth2Mixin):
|
||||
"""Google authentication using OAuth2."""
|
||||
"""Google authentication using OAuth2.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
"""
|
||||
_OAUTH_AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/auth"
|
||||
_OAUTH_ACCESS_TOKEN_URL = "https://accounts.google.com/o/oauth2/token"
|
||||
_OAUTH_NO_CALLBACKS = False
|
||||
@@ -961,22 +958,22 @@ class GoogleOAuth2Mixin(OAuth2Mixin):
|
||||
|
||||
Example usage::
|
||||
|
||||
class GoogleOAuth2LoginHandler(LoginHandler, tornado.auth.GoogleOAuth2Mixin):
|
||||
@tornado.web.asynchronous
|
||||
class GoogleOAuth2LoginHandler(LoginHandler,
|
||||
tornado.auth.GoogleOAuth2Mixin):
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("code", False):
|
||||
if self.get_argument('code', False):
|
||||
user = yield self.get_authenticated_user(
|
||||
redirect_uri='http://your.site.com/auth/google',
|
||||
code=self.get_argument("code"))
|
||||
code=self.get_argument('code'))
|
||||
# Save the user with e.g. set_secure_cookie
|
||||
else:
|
||||
yield self.authorize_redirect(
|
||||
redirect_uri='http://your.site.com/auth/google',
|
||||
client_id=self.settings["google_consumer_key"],
|
||||
scope=['openid', 'email'],
|
||||
client_id=self.settings['google_oauth']['key'],
|
||||
scope=['profile', 'email'],
|
||||
response_type='code',
|
||||
extra_params={"approval_prompt": "auto"})
|
||||
extra_params={'approval_prompt': 'auto'})
|
||||
"""
|
||||
http = self.get_auth_http_client()
|
||||
body = urllib_parse.urlencode({
|
||||
@@ -1234,7 +1231,6 @@ class FacebookGraphMixin(OAuth2Mixin):
|
||||
Example usage::
|
||||
|
||||
class FacebookGraphLoginHandler(LoginHandler, tornado.auth.FacebookGraphMixin):
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
if self.get_argument("code", False):
|
||||
@@ -1321,7 +1317,6 @@ class FacebookGraphMixin(OAuth2Mixin):
|
||||
class MainHandler(tornado.web.RequestHandler,
|
||||
tornado.auth.FacebookGraphMixin):
|
||||
@tornado.web.authenticated
|
||||
@tornado.web.asynchronous
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
new_entry = yield self.facebook_request(
|
||||
|
||||
@@ -55,7 +55,16 @@ _XHTML_ESCAPE_DICT = {'&': '&', '<': '<', '>': '>', '"': '"',
|
||||
|
||||
|
||||
def xhtml_escape(value):
|
||||
"""Escapes a string so it is valid within HTML or XML."""
|
||||
"""Escapes a string so it is valid within HTML or XML.
|
||||
|
||||
Escapes the characters ``<``, ``>``, ``"``, ``'``, and ``&``.
|
||||
When used in attribute values the escaped strings must be enclosed
|
||||
in quotes.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
|
||||
Added the single quote to the list of escaped characters.
|
||||
"""
|
||||
return _XHTML_ESCAPE_RE.sub(lambda match: _XHTML_ESCAPE_DICT[match.group(0)],
|
||||
to_basestring(value))
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ For more complicated interfaces, `Task` can be split into two parts:
|
||||
`Callback` and `Wait`::
|
||||
|
||||
class GenAsyncHandler2(RequestHandler):
|
||||
@asynchronous
|
||||
@gen.coroutine
|
||||
def get(self):
|
||||
http_client = AsyncHTTPClient()
|
||||
|
||||
@@ -301,6 +301,22 @@ class IOLoop(Configurable):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _setup_logging(self):
|
||||
"""The IOLoop catches and logs exceptions, so it's
|
||||
important that log output be visible. However, python's
|
||||
default behavior for non-root loggers (prior to python
|
||||
3.2) is to print an unhelpful "no handlers could be
|
||||
found" message rather than the actual log entry, so we
|
||||
must explicitly configure logging if we've made it this
|
||||
far without anything.
|
||||
|
||||
This method should be called from start() in subclasses.
|
||||
"""
|
||||
if not any([logging.getLogger().handlers,
|
||||
logging.getLogger('tornado').handlers,
|
||||
logging.getLogger('tornado.application').handlers]):
|
||||
logging.basicConfig()
|
||||
|
||||
def stop(self):
|
||||
"""Stop the I/O loop.
|
||||
|
||||
@@ -550,15 +566,7 @@ class PollIOLoop(IOLoop):
|
||||
action if action is not None else signal.SIG_DFL)
|
||||
|
||||
def start(self):
|
||||
if not logging.getLogger().handlers:
|
||||
# The IOLoop catches and logs exceptions, so it's
|
||||
# important that log output be visible. However, python's
|
||||
# default behavior for non-root loggers (prior to python
|
||||
# 3.2) is to print an unhelpful "no handlers could be
|
||||
# found" message rather than the actual log entry, so we
|
||||
# must explicitly configure logging if we've made it this
|
||||
# far without anything.
|
||||
logging.basicConfig()
|
||||
self._setup_logging()
|
||||
if self._stopped:
|
||||
self._stopped = False
|
||||
return
|
||||
|
||||
@@ -60,6 +60,13 @@ def _stderr_supports_color():
|
||||
return color
|
||||
|
||||
|
||||
def _safe_unicode(s):
|
||||
try:
|
||||
return _unicode(s)
|
||||
except UnicodeDecodeError:
|
||||
return repr(s)
|
||||
|
||||
|
||||
class LogFormatter(logging.Formatter):
|
||||
"""Log formatter used in Tornado.
|
||||
|
||||
@@ -73,23 +80,37 @@ class LogFormatter(logging.Formatter):
|
||||
`tornado.options.parse_command_line` (unless ``--logging=none`` is
|
||||
used).
|
||||
"""
|
||||
DEFAULT_PREFIX_FORMAT = '[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]'
|
||||
DEFAULT_FORMAT = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s'
|
||||
DEFAULT_DATE_FORMAT = '%y%m%d %H:%M:%S'
|
||||
DEFAULT_COLORS = {
|
||||
logging.DEBUG: 4, # Blue
|
||||
logging.INFO: 2, # Green
|
||||
logging.WARNING: 3, # Yellow
|
||||
logging.ERROR: 1, # Red
|
||||
}
|
||||
|
||||
def __init__(self, color=True, prefix_fmt=None, datefmt=None):
|
||||
def __init__(self, color=True, fmt=DEFAULT_FORMAT,
|
||||
datefmt=DEFAULT_DATE_FORMAT, colors=DEFAULT_COLORS):
|
||||
r"""
|
||||
:arg bool color: Enables color support
|
||||
:arg string prefix_fmt: Log message prefix format.
|
||||
Prefix is a part of the log message, directly preceding the actual
|
||||
message text.
|
||||
:arg bool color: Enables color support.
|
||||
:arg string fmt: Log message format.
|
||||
It will be applied to the attributes dict of log records. The
|
||||
text between ``%(color)s`` and ``%(end_color)s`` will be colored
|
||||
depending on the level if color support is on.
|
||||
:arg dict colors: color mappings from logging level to terminal color
|
||||
code
|
||||
:arg string datefmt: Datetime format.
|
||||
Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
|
||||
Added ``fmt`` and ``datefmt`` arguments.
|
||||
"""
|
||||
self.__prefix_fmt = prefix_fmt if prefix_fmt is not None else self.DEFAULT_PREFIX_FORMAT
|
||||
datefmt = datefmt if datefmt is not None else self.DEFAULT_DATE_FORMAT
|
||||
logging.Formatter.__init__(self, datefmt=datefmt)
|
||||
self._color = color and _stderr_supports_color()
|
||||
if self._color:
|
||||
self._fmt = fmt
|
||||
|
||||
self._colors = {}
|
||||
if color and _stderr_supports_color():
|
||||
# The curses module has some str/bytes confusion in
|
||||
# python3. Until version 3.2.3, most methods return
|
||||
# bytes, but only accept strings. In addition, we want to
|
||||
@@ -101,62 +122,56 @@ class LogFormatter(logging.Formatter):
|
||||
curses.tigetstr("setf") or "")
|
||||
if (3, 0) < sys.version_info < (3, 2, 3):
|
||||
fg_color = unicode_type(fg_color, "ascii")
|
||||
self._colors = {
|
||||
logging.DEBUG: unicode_type(curses.tparm(fg_color, 4), # Blue
|
||||
"ascii"),
|
||||
logging.INFO: unicode_type(curses.tparm(fg_color, 2), # Green
|
||||
"ascii"),
|
||||
logging.WARNING: unicode_type(curses.tparm(fg_color, 3), # Yellow
|
||||
"ascii"),
|
||||
logging.ERROR: unicode_type(curses.tparm(fg_color, 1), # Red
|
||||
"ascii"),
|
||||
}
|
||||
|
||||
for levelno, code in colors.items():
|
||||
self._colors[levelno] = unicode_type(curses.tparm(fg_color, code), "ascii")
|
||||
self._normal = unicode_type(curses.tigetstr("sgr0"), "ascii")
|
||||
else:
|
||||
self._normal = ''
|
||||
|
||||
def format(self, record):
|
||||
try:
|
||||
record.message = record.getMessage()
|
||||
message = record.getMessage()
|
||||
assert isinstance(message, basestring_type) # guaranteed by logging
|
||||
# Encoding notes: The logging module prefers to work with character
|
||||
# strings, but only enforces that log messages are instances of
|
||||
# basestring. In python 2, non-ascii bytestrings will make
|
||||
# their way through the logging framework until they blow up with
|
||||
# an unhelpful decoding error (with this formatter it happens
|
||||
# when we attach the prefix, but there are other opportunities for
|
||||
# exceptions further along in the framework).
|
||||
#
|
||||
# If a byte string makes it this far, convert it to unicode to
|
||||
# ensure it will make it out to the logs. Use repr() as a fallback
|
||||
# to ensure that all byte strings can be converted successfully,
|
||||
# but don't do it by default so we don't add extra quotes to ascii
|
||||
# bytestrings. This is a bit of a hacky place to do this, but
|
||||
# it's worth it since the encoding errors that would otherwise
|
||||
# result are so useless (and tornado is fond of using utf8-encoded
|
||||
# byte strings whereever possible).
|
||||
record.message = _safe_unicode(message)
|
||||
except Exception as e:
|
||||
record.message = "Bad message (%r): %r" % (e, record.__dict__)
|
||||
assert isinstance(record.message, basestring_type) # guaranteed by logging
|
||||
|
||||
record.asctime = self.formatTime(record, self.datefmt)
|
||||
prefix = self.__prefix_fmt % record.__dict__
|
||||
if self._color:
|
||||
prefix = (self._colors.get(record.levelno, self._normal) +
|
||||
prefix + self._normal)
|
||||
|
||||
# Encoding notes: The logging module prefers to work with character
|
||||
# strings, but only enforces that log messages are instances of
|
||||
# basestring. In python 2, non-ascii bytestrings will make
|
||||
# their way through the logging framework until they blow up with
|
||||
# an unhelpful decoding error (with this formatter it happens
|
||||
# when we attach the prefix, but there are other opportunities for
|
||||
# exceptions further along in the framework).
|
||||
#
|
||||
# If a byte string makes it this far, convert it to unicode to
|
||||
# ensure it will make it out to the logs. Use repr() as a fallback
|
||||
# to ensure that all byte strings can be converted successfully,
|
||||
# but don't do it by default so we don't add extra quotes to ascii
|
||||
# bytestrings. This is a bit of a hacky place to do this, but
|
||||
# it's worth it since the encoding errors that would otherwise
|
||||
# result are so useless (and tornado is fond of using utf8-encoded
|
||||
# byte strings whereever possible).
|
||||
def safe_unicode(s):
|
||||
try:
|
||||
return _unicode(s)
|
||||
except UnicodeDecodeError:
|
||||
return repr(s)
|
||||
if record.levelno in self._colors:
|
||||
record.color = self._colors[record.levelno]
|
||||
record.end_color = self._normal
|
||||
else:
|
||||
record.color = record.end_color = ''
|
||||
|
||||
formatted = self._fmt % record.__dict__
|
||||
|
||||
formatted = prefix + " " + safe_unicode(record.message)
|
||||
if record.exc_info:
|
||||
if not record.exc_text:
|
||||
record.exc_text = self.formatException(record.exc_info)
|
||||
if record.exc_text:
|
||||
# exc_text contains multiple lines. We need to safe_unicode
|
||||
# exc_text contains multiple lines. We need to _safe_unicode
|
||||
# each line separately so that non-utf8 bytes don't cause
|
||||
# all the newlines to turn into '\n'.
|
||||
lines = [formatted.rstrip()]
|
||||
lines.extend(safe_unicode(ln) for ln in record.exc_text.split('\n'))
|
||||
lines.extend(_safe_unicode(ln) for ln in record.exc_text.split('\n'))
|
||||
formatted = '\n'.join(lines)
|
||||
return formatted.replace("\n", "\n ")
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ python3.4 -m tornado.test.runtests --ioloop=tornado.platform.asyncio.AsyncIOMain
|
||||
(the tests log a few warnings with AsyncIOMainLoop because they leave some
|
||||
unfinished callbacks on the event loop that fail when it resumes)
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function, with_statement
|
||||
import asyncio
|
||||
import datetime
|
||||
import functools
|
||||
@@ -34,7 +36,10 @@ class BaseAsyncIOLoop(IOLoop):
|
||||
for fd in list(self.handlers):
|
||||
self.remove_handler(fd)
|
||||
if all_fds:
|
||||
os.close(fd)
|
||||
try:
|
||||
os.close(fd)
|
||||
except OSError:
|
||||
pass
|
||||
if self.close_loop:
|
||||
self.asyncio_loop.close()
|
||||
|
||||
@@ -86,6 +91,7 @@ class BaseAsyncIOLoop(IOLoop):
|
||||
self.handlers[fd](fd, events)
|
||||
|
||||
def start(self):
|
||||
self._setup_logging()
|
||||
self.asyncio_loop.run_forever()
|
||||
|
||||
def stop(self):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import absolute_import, division, print_function, with_statement
|
||||
import pycares
|
||||
import socket
|
||||
|
||||
|
||||
@@ -456,6 +456,7 @@ class TwistedIOLoop(tornado.ioloop.IOLoop):
|
||||
del self.fds[fd]
|
||||
|
||||
def start(self):
|
||||
self._setup_logging()
|
||||
self.reactor.run()
|
||||
|
||||
def stop(self):
|
||||
|
||||
@@ -516,6 +516,10 @@ class RequestHandler(object):
|
||||
|
||||
See `clear_cookie` for more information on the path and domain
|
||||
parameters.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
|
||||
Added the ``path`` and ``domain`` parameters.
|
||||
"""
|
||||
for name in self.request.cookies:
|
||||
self.clear_cookie(name, path=path, domain=domain)
|
||||
@@ -1850,6 +1854,11 @@ class StaticFileHandler(RequestHandler):
|
||||
class method. Instance methods may use the attributes ``self.path``
|
||||
``self.absolute_path``, and ``self.modified``.
|
||||
|
||||
Subclasses should only override methods discussed in this section;
|
||||
overriding other methods is error-prone. Overriding
|
||||
``StaticFileHandler.get`` is particularly problematic due to the
|
||||
tight coupling with ``compute_etag`` and other methods.
|
||||
|
||||
To change the way static urls are generated (e.g. to match the behavior
|
||||
of another server or CDN), override `make_static_url`, `parse_url_path`,
|
||||
`get_cache_time`, and/or `get_version`.
|
||||
|
||||
Reference in New Issue
Block a user