What’s new in Tornado 4.2

May 26, 2015

Backwards-compatibility notes

  • SSLIOStream.connect and IOStream.start_tls now validate certificates by default.
  • Certificate validation will now use the system CA root certificates instead of certifi when possible (i.e. Python 2.7.9+ or 3.4+). This includes IOStream and simple_httpclient, but not curl_httpclient.
  • The default SSL configuration has become stricter, using ssl.create_default_context where available on the client side. (On the server side, applications are encouraged to migrate from the ssl_options dict-based API to pass an ssl.SSLContext instead).
  • The deprecated classes in the tornado.auth module, GoogleMixin, FacebookMixin, and FriendFeedMixin have been removed.

New modules: tornado.locks and tornado.queues

These modules provide classes for coordinating coroutines, merged from Toro.

To port your code from Toro’s queues to Tornado 4.2, import Queue, PriorityQueue, or LifoQueue from tornado.queues instead of from toro.

Use Queue instead of Toro’s JoinableQueue. In Tornado the methods join and task_done are available on all queues, not on a special JoinableQueue.

Tornado queues raise exceptions specific to Tornado instead of reusing exceptions from the Python standard library. Therefore instead of catching the standard queue.Empty exception from Queue.get_nowait, catch the special tornado.queues.QueueEmpty exception, and instead of catching the standard queue.Full from Queue.get_nowait, catch tornado.queues.QueueFull.

To port from Toro’s locks to Tornado 4.2, import Condition, Event, Semaphore, BoundedSemaphore, or Lock from tornado.locks instead of from toro.

Toro’s Semaphore.wait allowed a coroutine to wait for the semaphore to be unlocked without acquiring it. This encouraged unorthodox patterns; in Tornado, just use acquire.

Toro’s Event.wait raised a Timeout exception after a timeout. In Tornado, Event.wait raises tornado.gen.TimeoutError.

Toro’s Condition.wait also raised Timeout, but in Tornado, the Future returned by Condition.wait resolves to False after a timeout:

@gen.coroutine
def await_notification():
    if not (yield condition.wait(timeout=timedelta(seconds=1))):
        print('timed out')
    else:
        print('condition is true')

In lock and queue methods, wherever Toro accepted deadline as a keyword argument, Tornado names the argument timeout instead.

Toro’s AsyncResult is not merged into Tornado, nor its exceptions NotReady and AlreadySet. Use a Future instead. If you wrote code like this:

from tornado import gen
import toro

result = toro.AsyncResult()

@gen.coroutine
def setter():
    result.set(1)

@gen.coroutine
def getter():
    value = yield result.get()
    print(value)  # Prints "1".

Then the Tornado equivalent is:

from tornado import gen
from tornado.concurrent import Future

result = Future()

@gen.coroutine
def setter():
    result.set_result(1)

@gen.coroutine
def getter():
    value = yield result
    print(value)  # Prints "1".

tornado.autoreload

  • Improved compatibility with Windows.
  • Fixed a bug in Python 3 if a module was imported during a reload check.

tornado.concurrent

  • run_on_executor now accepts arguments to control which attributes it uses to find the IOLoop and executor.

tornado.curl_httpclient

  • Fixed a bug that would cause the client to stop processing requests if an exception occurred in certain places while there is a queue.

tornado.escape

  • xhtml_escape now supports numeric character references in hex format ( )

tornado.gen

  • WaitIterator no longer uses weak references, which fixes several garbage-collection-related bugs.
  • tornado.gen.Multi and tornado.gen.multi_future (which are used when yielding a list or dict in a coroutine) now log any exceptions after the first if more than one Future fails (previously they would be logged when the Future was garbage-collected, but this is more reliable). Both have a new keyword argument quiet_exceptions to suppress logging of certain exception types; to use this argument you must call Multi or multi_future directly instead of simply yielding a list.
  • multi_future now works when given multiple copies of the same Future.
  • On Python 3, catching an exception in a coroutine no longer leads to leaks via Exception.__context__.

tornado.httpclient

tornado.ioloop

  • The IOLoop constructor now has a make_current keyword argument to control whether the new IOLoop becomes IOLoop.current().
  • Third-party implementations of IOLoop should accept **kwargs in their initialize methods and pass them to the superclass implementation.
  • PeriodicCallback is now more efficient when the clock jumps forward by a large amount.

tornado.iostream

  • SSLIOStream.connect and IOStream.start_tls now validate certificates by default.
  • New method SSLIOStream.wait_for_handshake allows server-side applications to wait for the handshake to complete in order to verify client certificates or use NPN/ALPN.
  • The Future returned by SSLIOStream.connect now resolves after the handshake is complete instead of as soon as the TCP connection is established.
  • Reduced logging of SSL errors.
  • BaseIOStream.read_until_close now works correctly when a streaming_callback is given but callback is None (i.e. when it returns a Future)

tornado.locale

tornado.log

tornado.process

tornado.simple_httpclient

  • Improved performance on Python 3 by reusing a single ssl.SSLContext.
  • New constructor argument max_body_size controls the maximum response size the client is willing to accept. It may be bigger than max_buffer_size if streaming_callback is used.

tornado.tcpserver

tornado.util

tornado.web

  • Key versioning support for cookie signing. cookie_secret application setting can now contain a dict of valid keys with version as key. The current signing key then must be specified via key_version setting.
  • Parsing of the If-None-Match header now follows the RFC and supports weak validators.
  • Passing secure=False or httponly=False to RequestHandler.set_cookie now works as expected (previously only the presence of the argument was considered and its value was ignored).
  • RequestHandler.get_arguments now requires that its strip argument be of type bool. This helps prevent errors caused by the slightly dissimilar interfaces between the singular and plural methods.
  • Errors raised in _handle_request_exception are now logged more reliably.
  • RequestHandler.redirect now works correctly when called from a handler whose path begins with two slashes.
  • Passing messages containing % characters to tornado.web.HTTPError no longer causes broken error messages.

tornado.websocket

  • The on_close method will no longer be called more than once.
  • When the other side closes a connection, we now echo the received close code back instead of sending an empty close frame.