Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
  • v3.1.0

    What's new in Tornado 3.1
    =========================
    
    Jun 15, 2013
    ------------
    
    Multiple modules
    ~~~~~~~~~~~~~~~~
    
    * Many reference cycles have been broken up throughout the package,
      allowing for more efficient garbage collection on CPython.
    * Silenced some log messages when connections are opened and immediately
      closed (i.e. port scans), or other situations related to closed
      connections.
    * Various small speedups: `.HTTPHeaders` case normalization, `.UIModule`
      proxy objects, precompile some regexes.
    
    `tornado.auth`
    ~~~~~~~~~~~~~~
    
    * `~tornado.auth.OAuthMixin` always sends ``oauth_version=1.0`` in its
      request as required by the spec.
    * `~tornado.auth.FacebookGraphMixin` now uses ``self._FACEBOOK_BASE_URL``
      in `~.FacebookGraphMixin.facebook_request` to allow the base url to be
      overridden.
    * The ``authenticate_redirect`` and ``authorize_redirect`` methods in the
      `tornado.auth` mixin classes all now return Futures.  These methods
      are asynchronous in `.OAuthMixin` and derived classes, although they
      do not take a callback.  The `.Future` these methods return must be
      yielded if they are called from a function decorated with `.gen.coroutine`
      (but not `.gen.engine`).
    * `.TwitterMixin` now uses ``/account/verify_credentials`` to get information
      about the logged-in user, which is more robust against changing screen
      names.
    * The ``demos`` directory (in the source distribution) has a new
      ``twitter`` demo using `.TwitterMixin`.
    
    `tornado.escape`
    ~~~~~~~~~~~~~~~~
    
    * `.url_escape` and `.url_unescape` have a new ``plus`` argument (defaulting
      to True for consistency with the previous behavior) which specifies
      whether they work like `urllib.parse.unquote` or `urllib.parse.unquote_plus`.
    
    `tornado.gen`
    ~~~~~~~~~~~~~
    
    * Fixed a potential memory leak with long chains of `tornado.gen` coroutines.
    
    `tornado.httpclient`
    ~~~~~~~~~~~~~~~~~~~~
    
    * `tornado.httpclient.HTTPRequest` takes a new argument ``auth_mode``,
      which can be either ``basic`` or ``digest``.  Digest authentication
      is only supported with ``tornado.curl_httpclient``.
    * ``tornado.curl_httpclient`` no longer goes into an infinite loop when
      pycurl returns a negative timeout.
    * ``curl_httpclient`` now supports the ``PATCH`` and ``OPTIONS`` methods
      without the use of ``allow_nonstandard_methods=True``.
    * Worked around a class of bugs in libcurl that would result in
      errors from `.IOLoop.update_handler` in various scenarios including
      digest authentication and socks proxies.
    * The ``TCP_NODELAY`` flag is now set when appropriate in ``simple_httpclient``.
    * ``simple_httpclient`` no longer logs exceptions, since those exceptions
      are made available to the caller as ``HTTPResponse.error``.
    
    `tornado.httpserver`
    ~~~~~~~~~~~~~~~~~~~~
    
    * `tornado.httpserver.HTTPServer` handles malformed HTTP headers more
      gracefully.
    * `.HTTPServer` now supports lists of IPs in ``X-Forwarded-For``
      (it chooses the last, i.e. nearest one).
    * Memory is now reclaimed promptly on CPython when an HTTP request
      fails because it exceeded the maximum upload size.
    * The ``TCP_NODELAY`` flag is now set when appropriate in `.HTTPServer`.
    * The `.HTTPServer` ``no_keep_alive`` option is now respected with
      HTTP 1.0 connections that explicitly pass ``Connection: keep-alive``.
    * The ``Connection: keep-alive`` check for HTTP 1.0 connections is now
      case-insensitive.
    * The `str` and `repr` of `tornado.httpserver.HTTPRequest` no longer
      include the request body, reducing log spam on errors (and potential
      exposure/retention of private data).
    
    `tornado.httputil`
    ~~~~~~~~~~~~~~~~~~
    
    * The cache used in `.HTTPHeaders` will no longer grow without bound.
    
    `tornado.ioloop`
    ~~~~~~~~~~~~~~~~
    
    * Some `.IOLoop` implementations (such as ``pyzmq``) accept objects
      other than integer file descriptors; these objects will now have
      their ``.close()`` method called when the ``IOLoop` is closed with
      ``all_fds=True``.
    * The stub handles left behind by `.IOLoop.remove_timeout` will now get
      cleaned up instead of waiting to expire.
    
    `tornado.iostream`
    ~~~~~~~~~~~~~~~~~~
    
    * Fixed a bug in `.BaseIOStream.read_until_close` that would sometimes
      cause data to be passed to the final callback instead of the streaming
      callback.
    * The `.IOStream` close callback is now run more reliably if there is
      an exception in ``_try_inline_read``.
    * New method `.BaseIOStream.set_nodelay` can be used to set the
      ``TCP_NODELAY`` flag.
    * Fixed a case where errors in ``SSLIOStream.connect`` (and
      ``SimpleAsyncHTTPClient``) were not being reported correctly.
    
    `tornado.locale`
    ~~~~~~~~~~~~~~~~
    
    * `.Locale.format_date` now works on Python 3.
    
    `tornado.netutil`
    ~~~~~~~~~~~~~~~~~
    
    * The default `.Resolver` implementation now works on Solaris.
    * `.Resolver` now has a `~.Resolver.close` method.
    * Fixed a potential CPU DoS when ``tornado.netutil.ssl_match_hostname``
      is used on certificates with an abusive wildcard pattern.
    * All instances of `.ThreadedResolver` now share a single thread pool,
      whose size is set by the first one to be created (or the static
      ``Resolver.configure`` method).
    * `.ExecutorResolver` is now documented for public use.
    * `.bind_sockets` now works in configurations with incomplete IPv6 support.
    
    `tornado.options`
    ~~~~~~~~~~~~~~~~~
    
    * `tornado.options.define` with ``multiple=True`` now works on Python 3.
    * `tornado.options.options` and other `.OptionParser` instances support some
      new dict-like methods: `~.OptionParser.items()`, iteration over keys,
      and (read-only) access to options with square braket syntax.
      `.OptionParser.group_dict` returns all options with a given group
      name, and `.OptionParser.as_dict` returns all options.
    
    `tornado.process`
    ~~~~~~~~~~~~~~~~~
    
    * `tornado.process.Subprocess` no longer leaks file descriptors into
      the child process, which fixes a problem in which the child could not
      detect that the parent process had closed its stdin pipe.
    * `.Subprocess.set_exit_callback` now works for subprocesses created
      without an explicit ``io_loop`` parameter.
    
    `tornado.stack_context`
    ~~~~~~~~~~~~~~~~~~~~~~~
    
    * `tornado.stack_context` has been rewritten and is now much faster.
    * New function `.run_with_stack_context` facilitates the use of stack
      contexts with coroutines.
    
    `tornado.tcpserver`
    ~~~~~~~~~~~~~~~~~~~
    
    * The constructors of `.TCPServer` and `.HTTPServer` now take a
      ``max_buffer_size`` keyword argument.
    
    `tornado.template`
    ~~~~~~~~~~~~~~~~~~
    
    * Some internal names used by the template system have been changed;
      now all "reserved" names in templates start with ``_tt_``.
    
    `tornado.testing`
    ~~~~~~~~~~~~~~~~~
    
    * `tornado.testing.AsyncTestCase.wait` now raises the correct exception
      when it has been modified by `tornado.stack_context`.
    * `tornado.testing.gen_test` can now be called as ``@gen_test(timeout=60)``
      to give some tests a longer timeout than others.
    * The environment variable ``ASYNC_TEST_TIMEOUT`` can now be set to
      override the default timeout for `.AsyncTestCase.wait` and `.gen_test`.
    * `.bind_unused_port` now passes ``None`` instead of ``0`` as the port
      to ``getaddrinfo``, which works better with some unusual network
      configurations.
    
    `tornado.util`
    ~~~~~~~~~~~~~~
    
    * `tornado.util.import_object` now works with top-level module names that
      do not contain a dot.
    * `tornado.util.import_object` now consistently raises `ImportError`
      instead of `AttributeError` when it fails.
    
    `tornado.web`
    ~~~~~~~~~~~~~
    
    * The ``handlers`` list passed to the `tornado.web.Application` constructor
      and `~tornado.web.Application.add_handlers` methods can now contain
      lists in addition to tuples and `~tornado.web.URLSpec` objects.
    * `tornado.web.StaticFileHandler` now works on Windows when the client
      passes an ``If-Modified-Since`` timestamp before 1970.
    * New method `.RequestHandler.log_exception` can be overridden to
      customize the logging behavior when an exception is uncaught.  Most
      apps that currently override ``_handle_request_exception`` can now
      use a combination of `.RequestHandler.log_exception` and
      `.write_error`.
    * `.RequestHandler.get_argument` now raises `.MissingArgumentError`
      (a subclass of `tornado.web.HTTPError`, which is what it raised previously)
      if the argument cannot be found.
    * `.Application.reverse_url` now uses `.url_escape` with ``plus=False``,
      i.e. spaces are encoded as ``%20`` instead of ``+``.
    * Arguments extracted from the url path are now decoded with
      `.url_unescape` with ``plus=False``, so plus signs are left as-is
      instead of being turned into spaces.
    * `.RequestHandler.send_error` will now only be called once per request,
      even if multiple exceptions are caught by the stack context.
    * The `tornado.web.asynchronous` decorator is no longer necessary for
      methods that return a `.Future` (i.e. those that use the `.gen.coroutine`
      or `.return_future` decorators)
    * `.RequestHandler.prepare` may now be asynchronous if it returns a
      `.Future`.  The `~tornado.web.asynchronous` decorator is not used with
      ``prepare``; one of the `.Future`-related decorators should be used instead.
    * ``RequestHandler.current_user`` may now be assigned to normally.
    * `.RequestHandler.redirect` no longer silently strips control characters
      and whitespace.  It is now an error to pass control characters, newlines
      or tabs.
    * `.StaticFileHandler` has been reorganized internally and now has additional
      extension points that can be overridden in subclasses.
    * `.StaticFileHandler` now supports HTTP ``Range`` requests.
      `.StaticFileHandler` is still not suitable for files too large to
      comfortably fit in memory, but ``Range`` support is necessary in some
      browsers to enable seeking of HTML5 audio and video.
    * `.StaticFileHandler` now uses longer hashes by default, and uses the same
      hashes for ``Etag`` as it does for versioned urls.
    * `.StaticFileHandler.make_static_url` and `.RequestHandler.static_url`
      now have an additional keyword argument ``include_version`` to suppress
      the url versioning.
    * `.StaticFileHandler` now reads its file in chunks, which will reduce
      memory fragmentation.
    * Fixed a problem with the ``Date`` header and cookie expiration dates
      when the system locale is set to a non-english configuration.
    
    `tornado.websocket`
    ~~~~~~~~~~~~~~~~~~~
    
    * `.WebSocketHandler` now catches `.StreamClosedError` and runs
      `~.WebSocketHandler.on_close` immediately instead of logging a
      stack trace.
    * New method `.WebSocketHandler.set_nodelay` can be used to set the
      ``TCP_NODELAY`` flag.
    
    `tornado.wsgi`
    ~~~~~~~~~~~~~~
    
    * Fixed an exception in `.WSGIContainer` when the connection is closed
      while output is being written.
  • v3.0.2

    What's new in Tornado 3.0.2
    ===========================
    
    Jun 2, 2013
    -----------
    
    * `tornado.auth.TwitterMixin` now defaults to version 1.1 of the
      Twitter API, instead of version 1.0 which is being `discontinued on
      June 11 <https://dev.twitter.com/calendar>`_.  It also now uses HTTPS
      when talking to Twitter.
    * Fixed a potential memory leak with a long chain of `.gen.coroutine`
      or `.gen.engine` functions.
  • v3.0.1

    What's new in Tornado 3.0.1
    ===========================
    
    Apr 8, 2013
    -----------
    
    * The interface of `tornado.auth.FacebookGraphMixin` is now consistent
      with its documentation and the rest of the module.  The
      ``get_authenticated_user`` and ``facebook_request`` methods return a
      ``Future`` and the ``callback`` argument is optional.
    * The `tornado.testing.gen_test` decorator will no longer be recognized
      as a (broken) test by ``nose``.
    * Work around a bug in Ubuntu 13.04 betas involving an incomplete backport
      of the `ssl.match_hostname` function.
    * `tornado.websocket.websocket_connect` now fails cleanly when it attempts
      to connect to a non-websocket url.
    * `tornado.testing.LogTrapTestCase` once again works with byte strings
      on Python 2.
    * The ``request`` attribute of `tornado.httpclient.HTTPResponse` is
      now always an `~tornado.httpclient.HTTPRequest`, never a ``_RequestProxy``.
    * Exceptions raised by the `tornado.gen` module now have better messages
      when tuples are used as callback keys.
  • v3.0.0

    What's new in Tornado 3.0
    =========================
    
    Mar 29, 2013
    ------------
    
    Highlights
    ^^^^^^^^^^
    
    * The ``callback`` argument to many asynchronous methods is now
      optional, and these methods return a `.Future`.  The `tornado.gen`
      module now understands ``Futures``, and these methods can be used
      directly without a `.gen.Task` wrapper.
    * New function `.IOLoop.current` returns the `.IOLoop` that is running
      on the current thread (as opposed to `.IOLoop.instance`, which
      returns a specific thread's (usually the main thread's) IOLoop.
    * New class `tornado.netutil.Resolver` provides an asynchronous
      interface to DNS resolution.  The default implementation is still
      blocking, but non-blocking implementations are available using one
      of three optional dependencies: `~tornado.netutil.ThreadedResolver`
      using the `concurrent.futures` thread pool,
      ``tornado.platform.caresresolver.CaresResolver`` using the ``pycares``
      library, or ``tornado.platform.twisted.TwistedResolver`` using ``twisted``
    * Tornado's logging is now less noisy, and it no longer goes directly
      to the root logger, allowing for finer-grained configuration.
    * New class `tornado.process.Subprocess` wraps `subprocess.Popen` with
      `.PipeIOStream` access to the child's file descriptors.
    * `.IOLoop` now has a static `configure <.Configurable.configure>`
      method like the one on `.AsyncHTTPClient`, which can be used to
      select an `.IOLoop` implementation other than the default.
    * `.IOLoop` can now optionally use a monotonic clock if available
      (see below for more details).
    
    Backwards-incompatible changes
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    * Python 2.5 is no longer supported.  Python 3 is now supported in a single
      codebase instead of using ``2to3``
    * The ``tornado.database`` module has been removed.  It is now available
      as a separate package, `torndb <https://github.com/bdarnell/torndb>`_
    * Functions that take an ``io_loop`` parameter now default to
      `.IOLoop.current()` instead of `.IOLoop.instance()`.
    * Empty HTTP request arguments are no longer ignored.  This applies to
      ``HTTPRequest.arguments`` and ``RequestHandler.get_argument[s]``
      in WSGI and non-WSGI modes.
    * On Python 3, `tornado.escape.json_encode` no longer accepts byte strings.
    * On Python 3, the ``get_authenticated_user`` methods in `tornado.auth`
      now return character strings instead of byte strings.
    * ``tornado.netutil.TCPServer`` has moved to its own module,
      `tornado.tcpserver`.
    * The Tornado test suite now requires ``unittest2`` when run on Python 2.6.
    
    Detailed changes by module
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    Multiple modules
    ~~~~~~~~~~~~~~~~
    
    * Tornado no longer logs to the root logger.  Details on the new logging
      scheme can be found under the `tornado.log` module.  Note that in some
      cases this will require that you add an explicit logging configuration
      in order to see any output (perhaps just calling ``logging.basicConfig()``),
      although both `.IOLoop.start()` and `tornado.options.parse_command_line`
      will do this for you.
    * On python 3.2+, methods that take an ``ssl_options`` argument (on
      `.SSLIOStream`, `.TCPServer`, and `.HTTPServer`) now accept either a
      dictionary of options or an `ssl.SSLContext` object.
    * New optional dependency on `concurrent.futures` to provide better support
      for working with threads.  `concurrent.futures` is in the standard library
      for Python 3.2+, and can be installed on older versions with
      ``pip install futures``.
    
    `tornado.autoreload`
    ~~~~~~~~~~~~~~~~~~~~
    
    * `tornado.autoreload` is now more reliable when there are errors at import
      time.
    * Calling `tornado.autoreload.start` (or creating an `.Application` with
      ``debug=True``) twice on the same `.IOLoop` now does nothing (instead of
      creating multiple periodic callbacks).  Starting autoreload on
      more than one `.IOLoop` in the same process now logs a warning.
    * Scripts run by autoreload no longer inherit ``__future__`` imports
      used by Tornado.
    
    `tornado.auth`
    ~~~~~~~~~~~~~~
    
    * On Python 3, the ``get_authenticated_user`` method family now returns
      character strings instead of byte strings.
    * Asynchronous methods defined in `tornado.auth` now return a
      `.Future`, and their ``callback`` argument is optional.  The
      ``Future`` interface is preferred as it offers better error handling
      (the previous interface just logged a warning and returned None).
    * The `tornado.auth` mixin classes now define a method
      ``get_auth_http_client``, which can be overridden to use a non-default
      `.AsyncHTTPClient` instance (e.g. to use a different `.IOLoop`)
    * Subclasses of `.OAuthMixin` are encouraged to override
      `.OAuthMixin._oauth_get_user_future` instead of ``_oauth_get_user``,
      although both methods are still supported.
    
    `tornado.concurrent`
    ~~~~~~~~~~~~~~~~~~~~
    
    * New module `tornado.concurrent` contains code to support working with
      `concurrent.futures`, or to emulate future-based interface when that module
      is not available.
    
    ``tornado.curl_httpclient``
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * Preliminary support for ``tornado.curl_httpclient`` on Python 3.  The latest
      official release of pycurl only supports Python 2, but Ubuntu has a
      port available in 12.10 (``apt-get install python3-pycurl``).  This port
      currently has bugs that prevent it from handling arbitrary binary data
      but it should work for textual (utf8) resources.
    * Fix a crash with libcurl 7.29.0 if a curl object is created and closed
      without being used.
    
    `tornado.escape`
    ~~~~~~~~~~~~~~~~
    
    * On Python 3, `~tornado.escape.json_encode` no longer accepts byte strings.
      This mirrors the behavior of the underlying json module.  Python 2 behavior
      is unchanged but should be faster.
    
    `tornado.gen`
    ~~~~~~~~~~~~~
    
    * New decorator ``@gen.coroutine`` is available as an alternative to
      ``@gen.engine``.  It automatically returns a
      `.Future`, and within the function instead of
      calling a callback you return a value with ``raise
      gen.Return(value)`` (or simply ``return value`` in Python 3.3).
    * Generators may now yield `.Future` objects.
    * Callbacks produced by `.gen.Callback` and `.gen.Task` are now automatically
      stack-context-wrapped, to minimize the risk of context leaks when used
      with asynchronous functions that don't do their own wrapping.
    * Fixed a memory leak involving generators, `.RequestHandler.flush`,
      and clients closing connections while output is being written.
    * Yielding a large list no longer has quadratic performance.
    
    `tornado.httpclient`
    ~~~~~~~~~~~~~~~~~~~~
    
    * `.AsyncHTTPClient.fetch` now returns a `.Future` and its callback argument
      is optional.  When the future interface is used, any error will be raised
      automatically, as if `.HTTPResponse.rethrow` was called.
    * `.AsyncHTTPClient.configure` and all `.AsyncHTTPClient` constructors
      now take a ``defaults`` keyword argument.  This argument should be a
      dictionary, and its values will be used in place of corresponding
      attributes of `~tornado.httpclient.HTTPRequest` that are not set.
    * All unset attributes of `tornado.httpclient.HTTPRequest` are now
      ``None``.  The default values of some attributes
      (``connect_timeout``, ``request_timeout``, ``follow_redirects``,
      ``max_redirects``, ``use_gzip``, ``proxy_password``,
      ``allow_nonstandard_methods``, and ``validate_cert`` have been moved
      from `~tornado.httpclient.HTTPRequest` to the client
      implementations.
    * The ``max_clients`` argument to `.AsyncHTTPClient` is now a keyword-only
      argument.
    * Keyword arguments to `.AsyncHTTPClient.configure` are no longer used
      when instantiating an implementation subclass directly.
    * Secondary `.AsyncHTTPClient` callbacks (``streaming_callback``,
      ``header_callback``, and ``prepare_curl_callback``) now respect
      `.StackContext`.
    
    `tornado.httpserver`
    ~~~~~~~~~~~~~~~~~~~~
    
    * `.HTTPServer` no longer logs an error when it is unable to read a second
      request from an HTTP 1.1 keep-alive connection.
    * `.HTTPServer` now takes a ``protocol`` keyword argument which can be set
      to ``https`` if the server is behind an SSL-decoding proxy that does not
      set any supported X-headers.
    * `tornado.httpserver.HTTPConnection` now has a ``set_close_callback``
      method that should be used instead of reaching into its ``stream``
      attribute.
    * Empty HTTP request arguments are no longer ignored.  This applies to
      ``HTTPRequest.arguments`` and ``RequestHandler.get_argument[s]``
      in WSGI and non-WSGI modes.
    
    `tornado.ioloop`
    ~~~~~~~~~~~~~~~~
    
    * New function `.IOLoop.current` returns the ``IOLoop`` that is running
      on the current thread (as opposed to `.IOLoop.instance`, which returns a
      specific thread's (usually the main thread's) IOLoop).
    * New method `.IOLoop.add_future` to run a callback on the IOLoop when
      an asynchronous `.Future` finishes.
    * `.IOLoop` now has a static `configure <.Configurable.configure>`
      method like the one on `.AsyncHTTPClient`, which can be used to
      select an `.IOLoop` implementation other than the default.
    * The `.IOLoop` poller implementations (``select``, ``epoll``, ``kqueue``)
      are now available as distinct subclasses of `.IOLoop`.  Instantiating
      `.IOLoop` will continue to automatically choose the best available
      implementation.
    * The `.IOLoop` constructor has a new keyword argument ``time_func``,
      which can be used to set the time function used when scheduling callbacks.
      This is most useful with the `time.monotonic` function, introduced
      in Python 3.3 and backported to older versions via the ``monotime``
      module.  Using a monotonic clock here avoids problems when the system
      clock is changed.
    * New function `.IOLoop.time` returns the current time according to the
      IOLoop.  To use the new monotonic clock functionality, all calls to
      `.IOLoop.add_timeout` must be either pass a `datetime.timedelta` or
      a time relative to `.IOLoop.time`, not `time.time`.  (`time.time` will
      continue to work only as long as the IOLoop's ``time_func`` argument
      is not used).
    * New convenience method `.IOLoop.run_sync` can be used to start an IOLoop
      just long enough to run a single coroutine.
    * New method `.IOLoop.add_callback_from_signal` is safe to use in a signal
      handler (the regular `.add_callback` method may deadlock).
    * `.IOLoop` now uses `signal.set_wakeup_fd` where available (Python 2.6+
      on Unix) to avoid a race condition that could result in Python signal
      handlers being delayed.
    * Method ``IOLoop.running()`` has been removed.
    * `.IOLoop` has been refactored to better support subclassing.
    * `.IOLoop.add_callback` and `.add_callback_from_signal` now take
      ``*args, **kwargs`` to pass along to the callback.
    
    `tornado.iostream`
    ~~~~~~~~~~~~~~~~~~
    
    * `.IOStream.connect` now has an optional ``server_hostname`` argument
      which will be used for SSL certificate validation when applicable.
      Additionally, when supported (on Python 3.2+), this hostname
      will be sent via SNI (and this is supported by ``tornado.simple_httpclient``)
    * Much of `.IOStream` has been refactored into a separate class
      `.BaseIOStream`.
    * New class `tornado.iostream.PipeIOStream` provides the IOStream
      interface on pipe file descriptors.
    * `.IOStream` now raises a new exception
      ``tornado.iostream.StreamClosedError`` when you attempt to read or
      write after the stream has been closed (by either side).
    * `.IOStream` now simply closes the connection when it gets an
      ``ECONNRESET`` error, rather than logging it as an error.
    * ``IOStream.error`` no longer picks up unrelated exceptions.
    * `.BaseIOStream.close` now has an ``exc_info`` argument (similar to the
      one used in the `logging` module) that can be used to set the stream's
      ``error`` attribute when closing it.
    * `.BaseIOStream.read_until_close` now works correctly when it is called
      while there is buffered data.
    * Fixed a major performance regression when run on PyPy (introduced in
      Tornado 2.3).
    
    `tornado.log`
    ~~~~~~~~~~~~~
    
    * New module containing `.enable_pretty_logging` and `.LogFormatter`,
      moved from the options module.
    * `.LogFormatter` now handles non-ascii data in messages and tracebacks better.
    
    `tornado.netutil`
    ~~~~~~~~~~~~~~~~~
    
    * New class `tornado.netutil.Resolver` provides an asynchronous
      interface to DNS resolution.  The default implementation is still
      blocking, but non-blocking implementations are available using one
      of three optional dependencies: `~tornado.netutil.ThreadedResolver`
      using the `concurrent.futures` thread pool,
      `tornado.platform.caresresolver.CaresResolver` using the ``pycares``
      library, or `tornado.platform.twisted.TwistedResolver` using ``twisted``
    * New function `tornado.netutil.is_valid_ip` returns true if a given string
      is a valid IP (v4 or v6) address.
    * `tornado.netutil.bind_sockets` has a new ``flags`` argument that can
      be used to pass additional flags to ``getaddrinfo``.
    * `tornado.netutil.bind_sockets` no longer sets ``AI_ADDRCONFIG``; this will
      cause it to bind to both ipv4 and ipv6 more often than before.
    * `tornado.netutil.bind_sockets` now works when Python was compiled
      with ``--disable-ipv6`` but IPv6 DNS resolution is available on the
      system.
    * ``tornado.netutil.TCPServer`` has moved to its own module, `tornado.tcpserver`.
    
    `tornado.options`
    ~~~~~~~~~~~~~~~~~
    
    * The class underlying the functions in `tornado.options` is now public
      (`tornado.options.OptionParser`).  This can be used to create multiple
      independent option sets, such as for subcommands.
    * `tornado.options.parse_config_file` now configures logging automatically
      by default, in the same way that `~tornado.options.parse_command_line` does.
    * New function `tornado.options.add_parse_callback` schedules a callback
      to be run after the command line or config file has been parsed.  The
      keyword argument ``final=False`` can be used on either parsing function
      to supress these callbacks.
    * `tornado.options.define` now takes a ``callback`` argument.  This callback
      will be run with the new value whenever the option is changed.  This is
      especially useful for options that set other options, such as by reading
      from a config file.
    * `tornado.options.parse_command_line` ``--help`` output now goes to ``stderr``
      rather than ``stdout``.
    * `tornado.options.options` is no longer a subclass of `dict`; attribute-style
      access is now required.
    * `tornado.options.options` (and `.OptionParser` instances generally) now
      have a `.mockable()` method that returns a wrapper object compatible with
      `mock.patch <unittest.mock.patch>`.
    * Function ``tornado.options.enable_pretty_logging`` has been moved to the
      `tornado.log` module.
    
    `tornado.platform.caresresolver`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * New module containing an asynchronous implementation of the `.Resolver`
      interface, using the ``pycares`` library.
    
    `tornado.platform.twisted`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * New class `tornado.platform.twisted.TwistedIOLoop` allows Tornado
      code to be run on the Twisted reactor (as opposed to the existing
      `.TornadoReactor`, which bridges the gap in the other direction).
    * New class `tornado.platform.twisted.TwistedResolver` is an asynchronous
      implementation of the `.Resolver` interface.
    
    `tornado.process`
    ~~~~~~~~~~~~~~~~~
    
    * New class `tornado.process.Subprocess` wraps `subprocess.Popen` with
      `.PipeIOStream` access to the child's file descriptors.
    
    ``tornado.simple_httpclient``
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * ``SimpleAsyncHTTPClient`` now takes a ``resolver`` keyword argument
      (which may be passed to either the constructor or `configure
      <.Configurable.configure>`), to allow it to use the new non-blocking
      `tornado.netutil.Resolver`.
    * When following redirects, ``SimpleAsyncHTTPClient`` now treats a 302
      response code the same as a 303.  This is contrary to the HTTP spec
      but consistent with all browsers and other major HTTP clients
      (including ``CurlAsyncHTTPClient``).
    * The behavior of ``header_callback`` with ``SimpleAsyncHTTPClient`` has
      changed and is now the same as that of ``CurlAsyncHTTPClient``.  The
      header callback now receives the first line of the response (e.g.
      ``HTTP/1.0 200 OK``) and the final empty line.
    * ``tornado.simple_httpclient`` now accepts responses with a 304
      status code that include a ``Content-Length`` header.
    * Fixed a bug in which ``SimpleAsyncHTTPClient`` callbacks were being run in the
      client's ``stack_context``.
    
    `tornado.stack_context`
    ~~~~~~~~~~~~~~~~~~~~~~~
    
    * `.stack_context.wrap` now runs the wrapped callback in a more consistent
      environment by recreating contexts even if they already exist on the
      stack.
    * Fixed a bug in which stack contexts could leak from one callback
      chain to another.
    * Yield statements inside a ``with`` statement can cause stack
      contexts to become inconsistent; an exception will now be raised
      when this case is detected.
    
    `tornado.template`
    ~~~~~~~~~~~~~~~~~~
    
    * Errors while rendering templates no longer log the generated code,
      since the enhanced stack traces (from version 2.1) should make this
      unnecessary.
    * The ``{% apply %}`` directive now works properly with functions that return
      both unicode strings and byte strings (previously only byte strings were
      supported).
    * Code in templates is no longer affected by Tornado's ``__future__`` imports
      (which previously included ``absolute_import`` and ``division``).
    
    `tornado.testing`
    ~~~~~~~~~~~~~~~~~
    
    * New function `tornado.testing.bind_unused_port` both chooses a port
      and binds a socket to it, so there is no risk of another process
      using the same port.  ``get_unused_port`` is now deprecated.
    * New decorator `tornado.testing.gen_test` can be used to allow for
      yielding `tornado.gen` objects in tests, as an alternative to the
      ``stop`` and ``wait`` methods of `.AsyncTestCase`.
    * `tornado.testing.AsyncTestCase` and friends now extend ``unittest2.TestCase``
      when it is available (and continue to use the standard ``unittest`` module
      when ``unittest2`` is not available)
    * `tornado.testing.ExpectLog` can be used as a finer-grained alternative
      to `tornado.testing.LogTrapTestCase`
    * The command-line interface to `tornado.testing.main` now supports
      additional arguments from the underlying `unittest` module:
      ``verbose``, ``quiet``, ``failfast``, ``catch``, ``buffer``.
    * The deprecated ``--autoreload`` option of `tornado.testing.main` has
      been removed.  Use ``python -m tornado.autoreload`` as a prefix command
      instead.
    * The ``--httpclient`` option of `tornado.testing.main` has been moved
      to ``tornado.test.runtests`` so as not to pollute the application
      option namespace.  The `tornado.options` module's new callback
      support now makes it easy to add options from a wrapper script
      instead of putting all possible options in `tornado.testing.main`.
    * `.AsyncHTTPTestCase` no longer calls `.AsyncHTTPClient.close` for tests
      that use the singleton `.IOLoop.instance`.
    * `.LogTrapTestCase` no longer fails when run in unknown logging
      configurations.  This allows tests to be run under nose, which does its
      own log buffering (`.LogTrapTestCase` doesn't do anything useful in this
      case, but at least it doesn't break things any more).
    
    ``tornado.util``
    ~~~~~~~~~~~~~~~~
    
    * ``tornado.util.b`` (which was only intended for internal use) is gone.
    
    `tornado.web`
    ~~~~~~~~~~~~~
    
    * `.RequestHandler.set_header` now overwrites previous header values
      case-insensitively.
    * `tornado.web.RequestHandler` has new attributes ``path_args`` and
      ``path_kwargs``, which contain the positional and keyword arguments
      that are passed to the ``get``/``post``/etc method.  These attributes
      are set before those methods are called, so they are available during
      ``prepare()``
    * `tornado.web.ErrorHandler` no longer requires XSRF tokens on ``POST``
      requests, so posts to an unknown url will always return 404 instead of
      complaining about XSRF tokens.
    * Several methods related to HTTP status codes now take a ``reason`` keyword
      argument to specify an alternate "reason" string (i.e. the "Not Found" in
      "HTTP/1.1 404 Not Found").  It is now possible to set status codes other
      than those defined in the spec, as long as a reason string is given.
    * The ``Date`` HTTP header is now set by default on all responses.
    * ``Etag``/``If-None-Match`` requests now work with `.StaticFileHandler`.
    * `.StaticFileHandler` no longer sets ``Cache-Control: public`` unnecessarily.
    * When gzip is enabled in a `tornado.web.Application`, appropriate
      ``Vary: Accept-Encoding`` headers are now sent.
    * It is no longer necessary to pass all handlers for a host in a single
      `.Application.add_handlers` call.  Now the request will be matched
      against the handlers for any ``host_pattern`` that includes the request's
      ``Host`` header.
    
    `tornado.websocket`
    ~~~~~~~~~~~~~~~~~~~
    
    * Client-side WebSocket support is now available:
      `tornado.websocket.websocket_connect`
    * `.WebSocketHandler` has new methods `~.WebSocketHandler.ping` and
      `~.WebSocketHandler.on_pong` to send pings to the browser (not
      supported on the ``draft76`` protocol)
  • v2.4.1

    What's new in Tornado 2.4.1
    ===========================
    
    Nov 24, 2012
    ------------
    
    Bug fixes
    ~~~~~~~~~
    
    * Fixed a memory leak in `tornado.stack_context` that was especially likely
      with long-running ``@gen.engine`` functions.
    * `tornado.auth.TwitterMixin` now works on Python 3.
    * Fixed a bug in which `IOStream.read_until_close` with a streaming callback
      would sometimes pass the last chunk of data to the final callback instead
      of the streaming callback.
  • v2.4.0

    What's new in Tornado 2.4
    =========================
    
    Sep 4, 2012
    -----------
    
    General
    ~~~~~~~
    
    * Fixed Python 3 bugs in `tornado.auth`, `tornado.locale`, and `tornado.wsgi`.
    
    HTTP clients
    ~~~~~~~~~~~~
    
    * Removed ``max_simultaneous_connections`` argument from `tornado.httpclient`
      (both implementations).  This argument hasn't been useful for some time
      (if you were using it you probably want ``max_clients`` instead)
    * `tornado.simple_httpclient` now accepts and ignores HTTP 1xx status
      responses.
    
    `tornado.ioloop` and `tornado.iostream`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * Fixed a bug introduced in 2.3 that would cause `IOStream` close callbacks
      to not run if there were pending reads.
    * Improved error handling in `SSLIOStream` and SSL-enabled `TCPServer`.
    * `SSLIOStream.get_ssl_certificate` now has a ``binary_form`` argument
      which is passed to ``SSLSocket.getpeercert``.
    * `SSLIOStream.write` can now be called while the connection is in progress,
      same as non-SSL `IOStream` (but be careful not to send sensitive data until
      the connection has completed and the certificate has been verified).
    * `IOLoop.add_handler` cannot be called more than once with the same file
      descriptor.  This was always true for ``epoll``, but now the other
      implementations enforce it too.
    * On Windows, `TCPServer` uses `SO_EXCLUSIVEADDRUSER` instead of `SO_REUSEADDR`.
    
    `tornado.template`
    ~~~~~~~~~~~~~~~~~~
    
    * ``{% break %}`` and ``{% continue %}`` can now be used looping constructs
      in templates.
    * It is no longer an error for an if/else/for/etc block in a template to
      have an empty body.
    
    `tornado.testing`
    ~~~~~~~~~~~~~~~~~
    
    * New class `tornado.testing.AsyncHTTPSTestCase` is like `AsyncHTTPTestCase`.
      but enables SSL for the testing server (by default using a self-signed
      testing certificate).
    * `tornado.testing.main` now accepts additional keyword arguments and forwards
      them to `unittest.main`.
    
    `tornado.web`
    ~~~~~~~~~~~~~
    
    * New method `RequestHandler.get_template_namespace` can be overridden to
      add additional variables without modifying keyword arguments to
      `render_string`.
    * `RequestHandler.add_header` now works with `WSGIApplication`.
    * `RequestHandler.get_secure_cookie` now handles a potential error case.
    * `RequestHandler.__init__` now calls ``super().__init__`` to ensure that
      all constructors are called when multiple inheritance is used.
    * Docs have been updated with a description of all available
      :py:attr:`Application settings <tornado.web.Application.settings>`
    
    Other modules
    ~~~~~~~~~~~~~
    
    * `OAuthMixin` now accepts ``"oob"`` as a ``callback_uri``.
    * `OpenIDMixin` now also returns the ``claimed_id`` field for the user.
    * `tornado.platform.twisted` shutdown sequence is now more compatible.
    * The logging configuration used in `tornado.options` is now more tolerant
      of non-ascii byte strings.
  • v2.3.0

    What's new in Tornado 2.3
    =========================
    
    May 31, 2012
    ------------
    
    HTTP clients
    ~~~~~~~~~~~~
    
    * `tornado.httpclient.HTTPClient` now supports the same constructor
      keyword arguments as `AsyncHTTPClient`.
    * The ``max_clients`` keyword argument to `AsyncHTTPClient.configure` now works.
    * `tornado.simple_httpclient` now supports the ``OPTIONS`` and ``PATCH``
      HTTP methods.
    * `tornado.simple_httpclient` is better about closing its sockets
      instead of leaving them for garbage collection.
    * `tornado.simple_httpclient` correctly verifies SSL certificates for
      URLs containing IPv6 literals (This bug affected Python 2.5 and 2.6).
    * `tornado.simple_httpclient` no longer includes basic auth credentials
      in the ``Host`` header when those credentials are extracted from the URL.
    * `tornado.simple_httpclient` no longer modifies the caller-supplied header
      dictionary, which caused problems when following redirects.
    * `tornado.curl_httpclient` now supports client SSL certificates (using
      the same ``client_cert`` and ``client_key`` arguments as
      `tornado.simple_httpclient`)
    
    HTTP Server
    ~~~~~~~~~~~
    
    * `HTTPServer` now works correctly with paths starting with ``//``
    * `HTTPHeaders.copy` (inherited from `dict.copy`) now works correctly.
    * `HTTPConnection.address` is now always the socket address, even for non-IP
      sockets.  `HTTPRequest.remote_ip` is still always an IP-style address
      (fake data is used for non-IP sockets)
    * Extra data at the end of multipart form bodies is now ignored, which fixes
      a compatibility problem with an iOS HTTP client library.
    
    ``IOLoop`` and ``IOStream``
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * `IOStream` now has an ``error`` attribute that can be used to determine
      why a socket was closed.
    * `tornado.iostream.IOStream.read_until` and ``read_until_regex`` are much
      faster with large input.
    * `IOStream.write` performs better when given very large strings.
    * `IOLoop.instance()` is now thread-safe.
    
    ``tornado.options``
    ~~~~~~~~~~~~~~~~~~~
    
    * `tornado.options` options with ``multiple=True`` that are set more than
      once now overwrite rather than append.  This makes it possible to override
      values set in `parse_config_file` with `parse_command_line`.
    * `tornado.options` ``--help`` output is now prettier.
    * `tornado.options.options` now supports attribute assignment.
    
    ``tornado.template``
    ~~~~~~~~~~~~~~~~~~~~
    
    * Template files containing non-ASCII (utf8) characters now work on Python 3
      regardless of the locale environment variables.
    * Templates now support ``else`` clauses in
      ``try``/``except``/``finally``/``else`` blocks.
    
    ``tornado.web``
    ~~~~~~~~~~~~~~~
    
    * `tornado.web.RequestHandler` now supports the ``PATCH`` HTTP method.
      Note that this means any existing methods named ``patch`` in
      ``RequestHandler`` subclasses will need to be renamed.
    * `tornado.web.addslash` and ``removeslash`` decorators now send permanent
      redirects (301) instead of temporary (302).
    * `RequestHandler.flush` now invokes its callback whether there was any data
      to flush or not.
    * Repeated calls to `RequestHandler.set_cookie` with the same name now
      overwrite the previous cookie instead of producing additional copies.
    * `tornado.web.OutputTransform.transform_first_chunk` now takes and returns
      a status code in addition to the headers and chunk.  This is a
      backwards-incompatible change to an interface that was never technically
      private, but was not included in the documentation and does not appear
      to have been used outside Tornado itself.
    * Fixed a bug on python versions before 2.6.5 when `URLSpec` regexes
      are constructed from unicode strings and keyword arguments are extracted.
    * The ``reverse_url`` function in the template namespace now comes from
      the `RequestHandler` rather than the `Application`.  (Unless overridden,
      `RequestHandler.reverse_url` is just an alias for the `Application`
      method).
    * The ``Etag`` header is now returned on 304 responses to an ``If-None-Match``
      request, improving compatibility with some caches.
    * `tornado.web` will no longer produce responses with status code 304
      that also have entity headers such as ``Content-Length``.
    
    Other modules
    ~~~~~~~~~~~~~
    
    * `tornado.auth.FacebookGraphMixin` no longer sends ``post_args`` redundantly
      in the url.
    * The ``extra_params`` argument to `tornado.escape.linkify` may now be
      a callable, to allow parameters to be chosen separately for each link.
    * `tornado.gen` no longer leaks `StackContexts` when a ``@gen.engine`` wrapped
      function is called repeatedly.
    * `tornado.locale.get_supported_locales` no longer takes a meaningless
      ``cls`` argument.
    * `StackContext` instances now have a deactivation callback that can be
      used to prevent further propagation.
    * `tornado.testing.AsyncTestCase.wait` now resets its timeout on each call.
    * `tornado.wsgi.WSGIApplication` now parses arguments correctly on Python 3.
    * Exception handling on Python 3 has been improved; previously some exceptions
      such as `UnicodeDecodeError` would generate `TypeErrors`
  • v2.2.1

    What's new in Tornado 2.2.1
    ===========================
    
    Apr 23, 2012
    ------------
    
    Security fixes
    ~~~~~~~~~~~~~~
    
    * `tornado.web.RequestHandler.set_header` now properly sanitizes input
      values to protect against header injection, response splitting, etc.
      (it has always attempted to do this, but the check was incorrect).
      Note that redirects, the most likely source of such bugs, are protected
      by a separate check in `RequestHandler.redirect`.
    
    Bug fixes
    ~~~~~~~~~
    
    * Colored logging configuration in `tornado.options` is compatible with
      Python 3.2.3 (and 3.3).
  • v2.2.0

    What's new in Tornado 2.2
    =========================
    
    Jan 30, 2012
    ------------
    
    Highlights
    ~~~~~~~~~~
    
    * Updated and expanded WebSocket support.
    * Improved compatibility in the Twisted/Tornado bridge.
    * Template errors now generate better stack traces.
    * Better exception handling in `tornado.gen`.
    
    Security fixes
    ~~~~~~~~~~~~~~
    
    * `tornado.simple_httpclient` now disables SSLv2 in all cases.  Previously
      SSLv2 would be allowed if the Python interpreter was linked against a
      pre-1.0 version of OpenSSL.
    
    Backwards-incompatible changes
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * `tornado.process.fork_processes` now raises `SystemExit` if all child
      processes exit cleanly rather than returning ``None``.  The old behavior
      was surprising and inconsistent with most of the documented examples
      of this function (which did not check the return value).
    * On Python 2.6, `tornado.simple_httpclient` only supports SSLv3.  This
      is because Python 2.6 does not expose a way to support both SSLv3 and TLSv1
      without also supporting the insecure SSLv2.
    * `tornado.websocket` no longer supports the older "draft 76" version
      of the websocket protocol by default, although this version can
      be enabled by overriding `tornado.websocket.WebSocketHandler.allow_draft76`.
    
    ``tornado.httpclient``
    ~~~~~~~~~~~~~~~~~~~~~~
    
    * `SimpleAsyncHTTPClient` no longer hangs on ``HEAD`` requests,
      responses with no content, or empty ``POST``/``PUT`` response bodies.
    * `SimpleAsyncHTTPClient` now supports 303 and 307 redirect codes.
    * `tornado.curl_httpclient` now accepts non-integer timeouts.
    * `tornado.curl_httpclient` now supports basic authentication with an
      empty password.
    
    ``tornado.httpserver``
    ~~~~~~~~~~~~~~~~~~~~~~
    
    * `HTTPServer` with ``xheaders=True`` will no longer accept
      ``X-Real-IP`` headers that don't look like valid IP addresses.
    * `HTTPServer` now treats the ``Connection`` request header as
      case-insensitive.
    
    ``tornado.ioloop`` and ``tornado.iostream``
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * `IOStream.write` now works correctly when given an empty string.
    * `IOStream.read_until` (and ``read_until_regex``) now perform better
      when there is a lot of buffered data, which improves peformance of
      `SimpleAsyncHTTPClient` when downloading files with lots of
      chunks.
    * `SSLIOStream` now works correctly when ``ssl_version`` is set to
      a value other than ``SSLv23``.
    * Idle ``IOLoops`` no longer wake up several times a second.
    * `tornado.ioloop.PeriodicCallback` no longer triggers duplicate callbacks
      when stopped and started repeatedly.
    
    ``tornado.template``
    ~~~~~~~~~~~~~~~~~~~~
    
    * Exceptions in template code will now show better stack traces that
      reference lines from the original template file.
    * ``{#`` and ``#}`` can now be used for comments (and unlike the old
      ``{% comment %}`` directive, these can wrap other template directives).
    * Template directives may now span multiple lines.
    
    ``tornado.web``
    ~~~~~~~~~~~~~~~
    
    * Now behaves better when given malformed ``Cookie`` headers
    * `RequestHandler.redirect` now has a ``status`` argument to send
      status codes other than 301 and 302.
    * New method `RequestHandler.on_finish` may be overridden for post-request
      processing (as a counterpart to `RequestHandler.prepare`)
    * `StaticFileHandler` now outputs ``Content-Length`` and ``Etag`` headers
      on ``HEAD`` requests.
    * `StaticFileHandler` now has overridable ``get_version`` and
      ``parse_url_path`` methods for use in subclasses.
    * `RequestHandler.static_url` now takes an ``include_host`` parameter
      (in addition to the old support for the `RequestHandler.include_host`
      attribute).
    
    ``tornado.websocket``
    ~~~~~~~~~~~~~~~~~~~~~
    
    * Updated to support the latest version of the protocol, as finalized
      in RFC 6455.
    * Many bugs were fixed in all supported protocol versions.
    * `tornado.websocket` no longer supports the older "draft 76" version
      of the websocket protocol by default, although this version can
      be enabled by overriding `tornado.websocket.WebSocketHandler.allow_draft76`.
    * `WebSocketHandler.write_message` now accepts a ``binary`` argument
      to send binary messages.
    * Subprotocols (i.e. the ``Sec-WebSocket-Protocol`` header) are now supported;
      see the `WebSocketHandler.select_subprotocol` method for details.
    * `WebSocketHandler.get_websocket_scheme` can be used to select the
      appropriate url scheme (``ws://`` or ``wss://``) in cases where
      `HTTPRequest.protocol` is not set correctly.
    
    Other modules
    ~~~~~~~~~~~~~
    
    * `tornado.auth.TwitterMixin.authenticate_redirect` now takes a
      ``callback_uri`` parameter.
    * `tornado.auth.TwitterMixin.twitter_request` now accepts both URLs and
      partial paths (complete URLs are useful for the search API which follows
      different patterns).
    * Exception handling in `tornado.gen` has been improved.  It is now possible
      to catch exceptions thrown by a ``Task``.
    * `tornado.netutil.bind_sockets` now works when ``getaddrinfo`` returns
      duplicate addresses.
    * `tornado.platform.twisted` compatibility has been significantly improved.
      Twisted version 11.1.0 is now supported in addition to 11.0.0.
    * `tornado.process.fork_processes` correctly reseeds the `random` module
      even when `os.urandom` is not implemented.
    * `tornado.testing.main` supports a new flag ``--exception_on_interrupt``,
      which can be set to false to make ``Ctrl-C`` kill the process more
      reliably (at the expense of stack traces when it does so).
    * `tornado.version_info` is now a four-tuple so official releases can be
      distinguished from development branches.
  • v2.1.1

    What's new in Tornado 2.1.1
    ===========================
    
    Oct 4, 2011
    -----------
    
    Bug fixes
    ~~~~~~~~~
    
    * Fixed handling of closed connections with the ``epoll`` (i.e. Linux)
      ``IOLoop``.  Previously, closed connections could be shut down too early,
      which most often manifested as "Stream is closed" exceptions in
      ``SimpleAsyncHTTPClient``.
    * Fixed a case in which chunked responses could be closed prematurely,
      leading to truncated output.
    * ``IOStream.connect`` now reports errors more consistently via logging
      and the close callback (this affects e.g. connections to localhost
      on FreeBSD).
    * ``IOStream.read_bytes`` again accepts both ``int`` and ``long`` arguments.
    * ``PeriodicCallback`` no longer runs repeatedly when ``IOLoop`` iterations
      complete faster than the resolution of ``time.time()`` (mainly a problem
      on Windows).
    
    Backwards-compatibility note
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    * Listening for ``IOLoop.ERROR`` alone is no longer sufficient for detecting
      closed connections on an otherwise unused socket.  ``IOLoop.ERROR`` must
      always be used in combination with ``READ`` or ``WRITE``.
Something went wrong with that request. Please try again.