diff --git a/docs/releases/next.rst b/docs/releases/next.rst index 424fbb98..6bda3d9c 100644 --- a/docs/releases/next.rst +++ b/docs/releases/next.rst @@ -49,6 +49,7 @@ Multiple modules * 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``. `tornado.httpserver` ~~~~~~~~~~~~~~~~~~~~ @@ -59,8 +60,7 @@ Multiple modules (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` - and ``simple_httpclient``. +* 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 @@ -89,8 +89,7 @@ Multiple modules callback. * The `.IOStream` close callback is now run more reliably if there is an exception in ``_try_inline_read``. -* New methods `.BaseIOStream.set_nodelay` and - `.WebSocketHandler.set_nodelay` can be used to set the +* 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. @@ -207,6 +206,12 @@ Multiple modules * Fixed a problem with the ``Date`` header and cookie expiration dates when the system locale is set to a non-english configuration. +`tornado.websocket` +~~~~~~~~~~~~~~~~~~~ + +* New method `.WebSocketHandler.set_nodelay` can be used to set the + ``TCP_NODELAY`` flag. + `tornado.wsgi` ~~~~~~~~~~~~~~ diff --git a/tornado/auth.py b/tornado/auth.py index f1856b1e..93fb6116 100644 --- a/tornado/auth.py +++ b/tornado/auth.py @@ -1205,6 +1205,12 @@ class FacebookGraphMixin(OAuth2Mixin): self.authorize_redirect() return self.finish("Posted a message!") + + The given path is relative to ``self._FACEBOOK_BASE_URL``, + by default "https://graph.facebook.com". + + .. versionchanged:: 3.1 + Added the ability to override ``self._FACEBOOK_BASE_URL``. """ url = self._FACEBOOK_BASE_URL + path all_args = {} diff --git a/tornado/escape.py b/tornado/escape.py index 0dedad5d..91c3e740 100644 --- a/tornado/escape.py +++ b/tornado/escape.py @@ -95,6 +95,9 @@ def url_escape(value, plus=True): as "+" instead of "%20". This is appropriate for query strings but not for the path component of a URL. Note that this default is the reverse of Python's urllib module. + + .. versionadded:: 3.1 + The ``plus`` argument """ quote = urllib_parse.quote_plus if plus else urllib_parse.quote return quote(utf8(value)) @@ -117,6 +120,9 @@ if sys.version_info[0] < 3: is appropriate for query strings and form-encoded values but not for the path component of a URL. Note that this default is the reverse of Python's urllib module. + + .. versionadded:: 3.1 + The ``plus`` argument """ unquote = (urllib_parse.unquote_plus if plus else urllib_parse.unquote) if encoding is None: @@ -139,6 +145,9 @@ else: is appropriate for query strings and form-encoded values but not for the path component of a URL. Note that this default is the reverse of Python's urllib module. + + .. versionadded:: 3.1 + The ``plus`` argument """ if encoding is None: if plus: diff --git a/tornado/httpclient.py b/tornado/httpclient.py index e0cff2ee..a34eb66b 100644 --- a/tornado/httpclient.py +++ b/tornado/httpclient.py @@ -311,6 +311,9 @@ class HTTPRequest(object): ``simple_httpclient`` and true in ``curl_httpclient`` :arg string client_key: Filename for client SSL key, if any :arg string client_cert: Filename for client SSL certificate, if any + + .. versionadded:: 3.1 + The ``auth_mode`` argument. """ if headers is None: headers = httputil.HTTPHeaders() diff --git a/tornado/httpserver.py b/tornado/httpserver.py index d2ac7c2f..5beebda5 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -379,7 +379,10 @@ class HTTPRequest(object): Client's IP address as a string. If ``HTTPServer.xheaders`` is set, will pass along the real IP address provided by a load balancer - in the ``X-Real-Ip`` header + in the ``X-Real-Ip`` or ``X-Forwarded-For`` header. + + .. versionchanged:: 3.1 + The list format of ``X-Forwarded-For`` is now supported. .. attribute:: protocol diff --git a/tornado/ioloop.py b/tornado/ioloop.py index bee3be48..5f37032f 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -232,6 +232,11 @@ class IOLoop(Configurable): be allowed to return before attempting to call `IOLoop.close()`. Therefore the call to `close` will usually appear just after the call to `start` rather than near the call to `stop`. + + .. versionchanged:: 3.1 + If the `IOLoop` implementation supports non-integer objects + for "file descriptors", those objects will have their + ``close`` method when ``all_fds`` is true. """ raise NotImplementedError() diff --git a/tornado/iostream.py b/tornado/iostream.py index 633737af..9f9a1e60 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -283,6 +283,8 @@ class BaseIOStream(object): additional bandwidth. This flag is currently defined only for TCP-based ``IOStreams``. + + .. versionadded:: 3.1 """ pass diff --git a/tornado/netutil.py b/tornado/netutil.py index 5e77bc10..a7ba082f 100644 --- a/tornado/netutil.py +++ b/tornado/netutil.py @@ -208,7 +208,11 @@ class Resolver(Configurable): raise NotImplementedError() def close(self): - """Closes the `Resolver`, freeing any resources used.""" + """Closes the `Resolver`, freeing any resources used. + + .. versionadded:: 3.1 + + """ pass diff --git a/tornado/options.py b/tornado/options.py index 86ceb8bc..1105c0e9 100644 --- a/tornado/options.py +++ b/tornado/options.py @@ -108,11 +108,17 @@ class OptionParser(object): return self._options[item].value() def items(self): - """A sequence of (name, value) pairs.""" + """A sequence of (name, value) pairs. + + .. versionadded:: 3.1 + """ return [(name, opt.value()) for name, opt in self._options.items()] def groups(self): - """The set of option-groups created by ``define``.""" + """The set of option-groups created by ``define``. + + .. versionadded:: 3.1 + """ return set(opt.group_name for opt in self._options.values()) def group_dict(self, group): @@ -129,13 +135,18 @@ class OptionParser(object): application = Application( handlers, **options.group_dict('application')) + + .. versionadded:: 3.1 """ return dict( (name, opt.value()) for name, opt in self._options.items() if not group or group == opt.group_name) def as_dict(self): - """The names and values of all options.""" + """The names and values of all options. + + .. versionadded:: 3.1 + """ return dict( (name, opt.value()) for name, opt in self._options.items()) diff --git a/tornado/stack_context.py b/tornado/stack_context.py index 2d17d990..b1e82b0e 100644 --- a/tornado/stack_context.py +++ b/tornado/stack_context.py @@ -369,6 +369,8 @@ def run_with_stack_context(context, func): @gen.coroutine def correct(): yield run_with_stack_context(StackContext(ctx), other_coroutine) + + .. versionadded:: 3.1 """ with context: return func() diff --git a/tornado/tcpserver.py b/tornado/tcpserver.py index 2d200e9d..8473a21a 100644 --- a/tornado/tcpserver.py +++ b/tornado/tcpserver.py @@ -77,6 +77,9 @@ class TCPServer(object): also be used in single-process servers if you want to create your listening sockets in some way other than `~tornado.netutil.bind_sockets`. + + .. versionadded:: 3.1 + The ``max_buffer_size`` argument. """ def __init__(self, io_loop=None, ssl_options=None, max_buffer_size=None): self.io_loop = io_loop diff --git a/tornado/testing.py b/tornado/testing.py index f537d90d..8355dcfc 100644 --- a/tornado/testing.py +++ b/tornado/testing.py @@ -86,6 +86,8 @@ def get_async_test_timeout(): """Get the global timeout setting for async tests. Returns a float, the timeout in seconds. + + .. versionadded:: 3.1 """ try: return float(os.environ.get('ASYNC_TEST_TIMEOUT')) @@ -228,12 +230,16 @@ class AsyncTestCase(unittest.TestCase): def wait(self, condition=None, timeout=None): """Runs the `.IOLoop` until stop is called or timeout has passed. - In the event of a timeout, an exception will be thrown. The default - timeout is 5 seconds; it may be overridden with a ``timeout`` keyword - argument or globally with the ASYNC_TEST_TIMEOUT environment variable. + In the event of a timeout, an exception will be thrown. The + default timeout is 5 seconds; it may be overridden with a + ``timeout`` keyword argument or globally with the + ``ASYNC_TEST_TIMEOUT`` environment variable. If ``condition`` is not None, the `.IOLoop` will be restarted after `stop()` until ``condition()`` returns true. + + .. versionchanged:: 3.1 + Added the ``ASYNC_TEST_TIMEOUT`` environment variable. """ if timeout is None: timeout = get_async_test_timeout() @@ -397,7 +403,7 @@ def gen_test(func=None, timeout=None): response = yield gen.Task(self.fetch('/')) By default, ``@gen_test`` times out after 5 seconds. The timeout may be - overridden globally with the ASYNC_TEST_TIMEOUT environment variable, + overridden globally with the ``ASYNC_TEST_TIMEOUT`` environment variable, or for each test with the ``timeout`` keyword argument:: class MyTest(AsyncHTTPTestCase): @@ -405,8 +411,9 @@ def gen_test(func=None, timeout=None): def test_something_slow(self): response = yield gen.Task(self.fetch('/')) - If both the environment variable and the parameter are set, ``gen_test`` - uses the maximum of the two. + .. versionadded:: 3.1 + The ``timeout`` argument and ``ASYNC_TEST_TIMEOUT`` environment + variable. """ if timeout is None: timeout = get_async_test_timeout() diff --git a/tornado/web.py b/tornado/web.py index 138a8131..a9243126 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -205,6 +205,9 @@ class RequestHandler(object): `asynchronous` decorator cannot be used on `prepare`). If this method returns a `.Future` execution will not proceed until the `.Future` is done. + + .. versionadded:: 3.1 + Asynchronous support. """ pass @@ -1211,6 +1214,8 @@ class RequestHandler(object): stack traces (on the ``tornado.general`` logger), and all other exceptions as errors with stack traces (on the ``tornado.application`` logger). + + .. versionadded:: 3.1 """ if isinstance(value, HTTPError): if value.log_message: @@ -1278,6 +1283,8 @@ def asynchronous(method): self.write("Downloaded!") self.finish() + .. versionadded:: 3.1 + The ability to use ``@gen.coroutine`` without ``@asynchronous``. """ # Delay the IOLoop import because it's not available on app engine. from tornado.ioloop import IOLoop @@ -1668,6 +1675,8 @@ class MissingArgumentError(HTTPError): This is a subclass of `HTTPError`, so if it is uncaught a 400 response code will be used instead of 500 (and a stack trace will not be logged). + + .. versionadded:: 3.1 """ def __init__(self, arg_name): super(MissingArgumentError, self).__init__( @@ -1760,6 +1769,9 @@ class StaticFileHandler(RequestHandler): static content from a database), override `get_content`, `get_content_size`, `get_modified_time`, `get_absolute_path`, and `validate_absolute_path`. + + .. versionchanged:: 3.1 + Many of the methods for subclasses were added in Tornado 3.1. """ CACHE_MAX_AGE = 86400 * 365 * 10 # 10 years @@ -1841,6 +1853,8 @@ class StaticFileHandler(RequestHandler): This allows efficient ``If-None-Match`` checks against cached versions, and sends the correct ``Etag`` for a partial response (i.e. the same ``Etag`` as the full file). + + .. versionadded:: 3.1 """ version_hash = self._get_cached_version(self.absolute_path) if not version_hash: @@ -1848,7 +1862,10 @@ class StaticFileHandler(RequestHandler): return '"%s"' % (version_hash, ) def set_headers(self): - """Sets the content and caching headers on the response.""" + """Sets the content and caching headers on the response. + + .. versionadded:: 3.1 + """ self.set_header("Accept-Ranges", "bytes") self.set_etag_header() @@ -1868,7 +1885,10 @@ class StaticFileHandler(RequestHandler): self.set_extra_headers(self.path) def should_return_304(self): - """Returns True if the headers indicate that we should return 304.""" + """Returns True if the headers indicate that we should return 304. + + .. versionadded:: 3.1 + """ if self.check_etag_header(): return True @@ -1895,6 +1915,8 @@ class StaticFileHandler(RequestHandler): it returns a filesystem path, but other strings may be used as long as they are unique and understood by the subclass's overridden `get_content`. + + .. versionadded:: 3.1 """ abspath = os.path.abspath(os.path.join(root, path)) return abspath @@ -1916,6 +1938,8 @@ class StaticFileHandler(RequestHandler): In instance methods, this method's result is available as ``self.absolute_path``. + + .. versionadded:: 3.1 """ root = os.path.abspath(root) # os.path.abspath strips a trailing / @@ -1951,6 +1975,8 @@ class StaticFileHandler(RequestHandler): This method should either return a byte string or an iterator of byte strings. The latter is preferred for large files as it helps reduce memory fragmentation. + + .. versionadded:: 3.1 """ with open(abspath, "rb") as file: if start is not None: @@ -1979,6 +2005,8 @@ class StaticFileHandler(RequestHandler): This class method may be overridden by subclasses. The default implementation is a hash of the file's contents. + + .. versionadded:: 3.1 """ data = cls.get_content(abspath) hasher = hashlib.md5() @@ -1999,6 +2027,8 @@ class StaticFileHandler(RequestHandler): This method may be overridden by subclasses. It will only be called if a partial result is requested from `get_content` + + .. versionadded:: 3.1 """ stat_result = self._stat() return stat_result[stat.ST_SIZE] @@ -2008,13 +2038,18 @@ class StaticFileHandler(RequestHandler): May be overridden in subclasses. Should return a `~datetime.datetime` object or None. + + .. versionadded:: 3.1 """ stat_result = self._stat() modified = datetime.datetime.utcfromtimestamp(stat_result[stat.ST_MTIME]) return modified def get_content_type(self): - """Returns the ``Content-Type`` header to be used for this request.""" + """Returns the ``Content-Type`` header to be used for this request. + + .. versionadded:: 3.1 + """ mime_type, encoding = mimetypes.guess_type(self.absolute_path) return mime_type @@ -2087,9 +2122,10 @@ class StaticFileHandler(RequestHandler): The returned value should be a string, or ``None`` if no version could be determined. - This method was previously recommended for subclasses to override; - `get_content_version` is now preferred as it allows the base - class to handle caching of the result. + .. versionchanged:: 3.1 + This method was previously recommended for subclasses to override; + `get_content_version` is now preferred as it allows the base + class to handle caching of the result. """ abs_path = cls.get_absolute_path(settings['static_path'], path) return cls._get_cached_version(abs_path) diff --git a/tornado/websocket.py b/tornado/websocket.py index e0a5e1ae..8435e28a 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -238,6 +238,8 @@ class WebSocketHandler(tornado.web.RequestHandler): connection is established. See `.BaseIOStream.set_nodelay` for additional details. + + .. versionadded:: 3.1 """ self.stream.set_nodelay(value)