-``tornado.concurrent`` --- Work with threads and futures
-========================================================
+``tornado.concurrent`` --- Work with ``Future`` objects
+=======================================================
.. testsetup::
.. automodule:: tornado.concurrent
:members:
- :exclude-members: Future
- .. autoclass:: Future
+ .. class:: Future
- Consumer methods
- ^^^^^^^^^^^^^^^^
+ ``tornado.concurrent.Future`` is an alias for `asyncio.Future`
+ on Python 3. On Python 2, it provides an equivalent
+ implementation.
- .. automethod:: Future.result
- .. automethod:: Future.exception
- .. automethod:: Future.add_done_callback
- .. automethod:: Future.done
- .. automethod:: Future.cancel
- .. automethod:: Future.cancelled
+ In Tornado, the main way in which applications interact with
+ ``Future`` objects is by ``awaiting`` or ``yielding`` them in
+ coroutines, instead of calling methods on the ``Future`` objects
+ themselves. For more information on the available methods, see
+ the `asyncio.Future` docs.
- Producer methods
- ^^^^^^^^^^^^^^^^
+ .. versionchanged:: 5.0
- .. automethod:: Future.set_result
- .. automethod:: Future.set_exception
+ Tornado's implementation of ``Future`` has been replaced by
+ the version from `asyncio` when available.
+
+ - ``Future`` objects can only be created while there is a
+ current `.IOLoop`
+ - The timing of callbacks scheduled with
+ ``Future.add_done_callback`` has changed.
+ - Cancellation is now partially supported (only on Python 3)
+ - The ``exc_info`` and ``set_exc_info`` methods are no longer
+ available on Python 3.
]
intersphinx_mapping = {
- 'python': ('https://docs.python.org/3.5/', None),
+ 'python': ('https://docs.python.org/3.6/', None),
}
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
The raw `.Future` version is more complex, but ``Futures`` are
nonetheless recommended practice in Tornado because they have two
major advantages. Error handling is more consistent since the
-`.Future.result` method can simply raise an exception (as opposed to
+``Future.result`` method can simply raise an exception (as opposed to
the ad-hoc error handling common in callback-oriented interfaces), and
``Futures`` lend themselves well to use with coroutines. Coroutines
will be discussed in depth in the next section of this guide. Here is
auth
wsgi
- asyncio
caresresolver
twisted
+ asyncio
.. automethod:: IOLoop.call_later
.. automethod:: IOLoop.remove_timeout
.. automethod:: IOLoop.spawn_callback
+ .. automethod:: IOLoop.run_in_executor
+ .. automethod:: IOLoop.set_default_executor
.. automethod:: IOLoop.time
.. autoclass:: PeriodicCallback
:members:
.. toctree::
:maxdepth: 2
+ releases/v5.0.0
releases/v4.5.1
releases/v4.5.0
releases/v4.4.3
--- /dev/null
+What's new in Tornado 5.0
+=========================
+
+In progress
+-----------
+
+Highlights
+~~~~~~~~~~
+
+- The focus of this release is improving integration with `asyncio`.
+ On Python 3, the `.IOLoop` is always a wrapper around the `asyncio`
+ event loop, and `asyncio.Future` and `asyncio.Task` are used instead
+ of their Tornado counterparts. This means that libraries based on
+ `asyncio` can be mixed relatively seamlessly with those using
+ Tornado. While care has been taken to minimize the disruption from
+ this change, code changes may be required for compatibility with
+ Tornado 5.0, as detailed in the following section.
+- Support for Python 2.7 and 3.4 are deprecated; Tornado 6.0 will
+ require Python 3.5+. TODO(bdarnell): decide whether to drop py2 in 5.0
+
+Backwards-compatibility notes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Python 3.3 is no longer supported.
+- Versions of Python 2.7 that predate the `ssl` module update are no
+ longer supported. (The `ssl` module was updated in version 2.7.9,
+ although in some distributions the updates are present in builds
+ with a lower version number. Tornado requires `ssl.SSLContext`,
+ `ssl.create_default_context`, and `ssl.match_hostname`)
+- Versions of Python 3.5 prior to 3.5.2 are no longer supported due to
+ a change in the async iterator protocol in that version.
+- The ``trollius`` project (`asyncio` backported to Python 2) is no
+ longer supported.
+- `tornado.concurrent.Future` is now an alias for `asyncio.Future`
+ when running on Python 3. This results in a number of minor
+ behavioral changes:
+
+ - `.Future` objects can only be created while there is a current
+ `.IOLoop`
+ - The timing of callbacks scheduled with
+ ``Future.add_done_callback`` has changed.
+ `tornado.concurrent.future_add_done_callback` can be used to
+ make the behavior more like older versions of Tornado (but not
+ identical). Some of these changes are also present in the Python
+ 2 version of `tornado.concurrent.Future` to minimize the
+ difference between Python 2 and 3.
+ - Cancellation is now partially supported, via
+ `asyncio.Future.cancel`. A canceled `.Future` can no longer have
+ its result set. Applications that handle `~asyncio.Future`
+ objects directly may want to use
+ `tornado.concurrent.future_set_result_unless_cancelled`. In
+ native coroutines, cancellation will cause an exception to be
+ raised in the coroutine.
+ - The ``exc_info`` and ``set_exc_info`` methods are no longer
+ present. Use `tornado.concurrent.future_set_exc_info` to replace
+ the latter, and raise the exception with
+ `~asyncio.Future.result` to replace the former.
+- ``io_loop`` arguments to many Tornado functions have been removed.
+ Use `.IOLoop.current()` instead of passing `.IOLoop` objects
+ explicitly.
+- On Python 3, `.IOLoop` is always a wrapper around the `asyncio`
+ event loop. ``IOLoop.configure`` is effectively removed on Python 3
+ (for compatibility, it may be called to redundantly specify the
+ `asyncio`-backed `.IOLoop`)
+- `.IOLoop.instance` is now a deprecated alias for `.IOLoop.current`.
+ Applications that need the cross-thread communication behavior
+ facilitated by `.IOLoop.instance` should use their own global variable
+ instead.
+
+
+Other notes
+~~~~~~~~~~~
+
+- The ``certifi`` and ``backports.ssl-match-hostname`` packages are no
+ longer required on Python 2.7.
+- Python 3.6 or higher is recommended, because it features more
+ efficient garbage collection of `asyncio.Future` objects.
+
+`tornado.autoreload`
+~~~~~~~~~~~~~~~~~~~~
+
+- On Python 3, uses ``__main__.__spec`` to more reliably reconstruct
+ the original command line and avoid modifying ``PYTHONPATH``.
+- The ``io_loop`` argument to `tornado.autoreload.start` has been removed.
+
+`tornado.concurrent`
+~~~~~~~~~~~~~~~~~~~~
+
+- `tornado.concurrent.Future` is now an alias for `asyncio.Future`
+ when running on Python 3. See "Backwards-compatibility notes" for
+ more.
+- Setting the result of a ``Future`` no longer blocks while callbacks
+ are being run. Instead, the callbacks are scheduled on the next
+ `.IOLoop` iteration.
+- The deprecated alias ``tornado.concurrent.TracebackFuture`` has been
+ removed.
+- `tornado.concurrent.chain_future` now works with all three kinds of
+ ``Futures`` (Tornado, `asyncio`, and `concurrent.futures`)
+- The ``io_loop`` argument to `tornado.concurrent.run_on_executor` has
+ been removed.
+- New functions `.future_set_result_unless_cancelled`,
+ `.future_set_exc_info`, and `.future_add_done_callback` help mask
+ the difference between `asyncio.Future` and Tornado's previous
+ ``Future`` implementation.
+
+`tornado.curl_httpclient`
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Improved debug logging on Python 3.
+- The ``time_info`` response attribute now includes ``appconnect`` in
+ addition to other measurements.
+- Closing a `.CurlAsyncHTTPClient` now breaks circular references that
+ could delay garbage collection.
+- The ``io_loop`` argument to the `.CurlAsyncHTTPClient` constructor
+ has been removed.
+
+`tornado.gen`
+~~~~~~~~~~~~~
+
+- ``tornado.gen.TimeoutError`` is now an alias for
+ `tornado.util.TimeoutError`.
+- Leak detection for ``Futures`` created by this module now attributes
+ them to their proper caller instead of the coroutine machinery.
+- Several circular references that could delay garbage collection have
+ been broken up.
+- On Python 3, `asyncio.Task` is used instead of the Tornado coroutine
+ runner. This improves compatibility with some `asyncio` libraries
+ and adds support for cancellation.
+- The ``io_loop`` arguments to ``YieldFuture`` and `.with_timeout` have
+ been removed.
+
+`tornado.httpclient`
+~~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to all `.AsyncHTTPClient` constructors has
+ been removed.
+
+`tornado.httpserver`
+~~~~~~~~~~~~~~~~~~~~
+
+- If a client sends a malformed request, the server now responds with
+ a 400 error instead of simply closing the connection.
+- ``Content-Length`` and ``Transfer-Encoding`` headers are no longer
+ sent with 1xx or 204 responses (this was already true of 304
+ responses).
+- When closing a connection to a HTTP/1.1 client, the ``Connection:
+ close`` header is sent with the response.
+- The ``io_loop`` argument to the `.HTTPServer` constructor has been
+ removed.
+- If more than one ``X-Scheme`` or ``X-Forwarded-Proto`` header is
+ present, only the last is used.
+
+`tornado.httputil`
+~~~~~~~~~~~~~~~~~~
+
+- The string representation of `.HTTPServerRequest` objects (which are
+ sometimes used in log messages) no longer includes the request
+ headers.
+- New function `.qs_to_qsl` converts the result of
+ `urllib.parse.parse_qs` to name-value pairs.
+
+`tornado.ioloop`
+~~~~~~~~~~~~~~~~
+
+- ``tornado.ioloop.TimeoutError`` is now an alias for
+ `tornado.util.TimeoutError`.
+- `.IOLoop.instance` is now a deprecated alias for `.IOLoop.current`.
+- `.IOLoop.initialized`, `.IOLoop.install`, and
+ `.IOLoop.clear_instance` are all deprecated.
+- On Python 3, the `asyncio`-backed `.IOLoop` is always used and
+ alternative `.IOLoop` implementations cannot be configured.
+- `~.IOLoop.run_sync` cancels its argument on a timeout. This
+ results in better stack traces (and avoids log messages about leaks)
+ in native coroutines.
+- New methods `.IOLoop.run_in_executor` and
+ `.IOLoop.set_default_executor` make it easier to run functions in
+ other threads from native coroutines (since
+ `concurrent.futures.Future` does not support ``await``).
+- ``PollIOLoop`` (the default on Python 2) attempts to detect misuse
+ of `.IOLoop` instances across `os.fork`.
+- The ``io_loop`` argument to `.PeriodicCallback` has been removed.
+- It is now possible to create a `.PeriodicCallback` in one thread
+ and start it in another without passing an explicit event loop.
+- The `.IOLoop.set_blocking_signal_threshold` and
+ `.IOLoop.set_blocking_log_threshold` methods are deprecated because
+ they are not implemented for the `asyncio` event loop`. Use the
+ ``PYTHONASYNCIODEBUG=1`` environment variable instead.
+
+`tornado.iostream`
+~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to the `.IOStream` constructor has been removed.
+- `.BaseIOStream.write` is now much more efficient for very large amounts of data.
+- Fixed some cases in which ``IOStream.error`` could be inaccurate.
+- Writing a `memoryview` can no longer result in "BufferError:
+ Existing exports of data: object cannot be re-sized".
+
+`tornado.locks`
+~~~~~~~~~~~~~~~
+
+- As a side effect of the ``Future`` changes, waiters are always
+ notified asynchronously with respect to `.Condition.notify`.
+
+`tornado.netutil`
+~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` arguments to `.add_accept_handler`,
+ `.ExecutorResolver`, and `.ThreadedResolver` have been removed.
+- `.add_accept_handler` returns a callable which can be used to remove
+ all handlers that were added.
+
+`tornado.options`
+~~~~~~~~~~~~~~~~~
+
+- Duplicate option names are now detected properly whether they use
+ hyphens or underscores.
+
+`tornado.platform.asyncio`
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- `.AsyncIOLoop` and `.AsyncIOMainLoop` are now used automatically
+ when appropriate; referencing them explicitly is no longer
+ recommended.
+- Starting an `.IOLoop` or making it current now also sets the
+ `asyncio` event loop for the current thread.
+- `.to_tornado_future` and `.to_asyncio_future` are deprecated since
+ they are now no-ops.
+
+`tornado.platform.caresresolver`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to `.CaresResolver` has been removed.
+
+`tornado.platform.twisted`
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` arguments to `.TornadoReactor`, `.TwistedResolver`,
+ and `tornado.platform.twisted.install` have been removed.
+
+`tornado.process`
+~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to the `.Subprocess` constructor and
+ `.Subprocess.initialize` has been removed.
+
+`tornado.routing`
+~~~~~~~~~~~~~~~~~
+
+- A default 404 response is now generated if no delegate is found for
+ a request.
+
+`tornado.simple_httpclient`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to `.SimpleAsyncHTTPClient` has been removed.
+- TLS is now configured according to `ssl.create_default_context` by
+ default.
+
+`tornado.tcpclient`
+~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to the `.TCPClient` constructor has been
+ removed.
+- `.TCPClient.connect` has a new ``timeout`` argument.
+
+`tornado.tcpserver`
+~~~~~~~~~~~~~~~~~~~
+
+- The ``io_loop`` argument to the `.TCPServer` constructor has been
+ removed.
+- `.TCPServer` no longer logs ``EBADF`` errors during shutdown.
+
+`tornado.testing`
+~~~~~~~~~~~~~~~~~
+
+- The deprecated ``tornado.testing.get_unused_port`` and
+ ``tornado.testing.LogTrapTestCase`` have been removed.
+- `.AsyncHTTPTestCase.fetch` now supports absolute URLs.
+
+`tornado.util`
+~~~~~~~~~~~~~~
+
+- `tornado.util.TimeoutError` replaces ``tornado.gen.TimeoutError``
+ and ``tornado.ioloop.TimeoutError``.
+- `.Configurable` now supports configuration at multiple levels of an
+ inheritance hierarchy.
+
+`tornado.web`
+~~~~~~~~~~~~~
+
+- `.RequestHandler.set_status` no longer requires that the given
+ status code appear in `http.client.responses`.
+- It is no longer allowed to send a body with 1xx or 204 responses.
+- Exception handling now breaks up reference cycles that could delay
+ garbage collection.
+- `.RedirectHandler` now copies any query arguments from the request
+ to the redirect location.
+
+`tornado.websocket`
+~~~~~~~~~~~~~~~~~~~
+
+- The C accelerator now operates on multiple bytes at a time to
+ improve performance.
+- Requests with invalid websocket headers now get a response with
+ status code 400 instead of a closed connection.
+- `.WebSocketHandler.write_message` now raises `.StreamClosedError` if
+ called after the connection is closed.
+ TODO(bdarnell): fix this up with WebSocketClosedError
+- The ``io_loop`` argument to `.websocket_connect` has been removed.
def foo(self):
pass
+ This decorator should not be confused with the similarly-named
+ `.IOLoop.run_in_executor`.
+
.. versionchanged:: 4.2
Added keyword arguments to use alternative attributes.
From the caller's perspective, the callback argument is optional.
If one is given, it will be invoked when the function is complete
- with `Future.result()` as an argument. If the function fails, the
+ with ``Future.result()`` as an argument. If the function fails, the
callback will not be run and an exception will be raised into the
surrounding `.StackContext`.
The result (success or failure) of ``a`` will be copied to ``b``, unless
``b`` has already been completed or cancelled by the time ``a`` finishes.
- Accepts both Tornado/asyncio `Future` objects and `concurrent.futures.Future`.
+ .. versionchanged:: 5.0
+
+ Now accepts both Tornado/asyncio `Future` objects and
+ `concurrent.futures.Future`.
+
"""
def copy(future):
assert future is a
``callback`` is invoked with one argument, the ``future``.
If ``future`` is already done, ``callback`` is invoked immediately.
- This may differ from the behavior of `.Future.add_done_callback`,
+ This may differ from the behavior of ``Future.add_done_callback``,
which makes no such guarantee.
+
+ .. versionadded:: 5.0
"""
if future.done():
callback(future)
:hide:
Most asynchronous functions in Tornado return a `.Future`;
-yielding this object returns its `~.Future.result`.
+yielding this object returns its ``Future.result``.
You can also yield a list or dict of ``Futures``, which will be
started at the same time and run in parallel; a list or dict of results will
def qs_to_qsl(qs):
- """Generator rewinding a result of ``parse_qs`` back to name-value pairs.
+ """Generator converting a result of ``parse_qs`` back to name-value pairs.
+
+ .. versionadded:: 5.0
"""
for k, vs in qs.items():
for v in vs:
"""An I/O event loop for non-blocking sockets.
-Typical applications will use a single `IOLoop` object, in the
-`IOLoop.instance` singleton. The `IOLoop.start` method should usually
-be called at the end of the ``main()`` function. Atypical applications may
-use more than one `IOLoop`, such as one `IOLoop` per thread, or per `unittest`
-case.
-
-In addition to I/O events, the `IOLoop` can also schedule time-based events.
-`IOLoop.add_timeout` is a non-blocking alternative to `time.sleep`.
+On Python 3, `.IOLoop` is a wrapper around the `asyncio` event loop.
+
+Typical applications will use a single `IOLoop` object, accessed via
+`IOLoop.current` class method. The `IOLoop.start` method (or
+equivalently, `asyncio.AbstractEventLoop.run_forever`) should usually
+be called at the end of the ``main()`` function. Atypical applications
+may use more than one `IOLoop`, such as one `IOLoop` per thread, or
+per `unittest` case.
+
+In addition to I/O events, the `IOLoop` can also schedule time-based
+events. `IOLoop.add_timeout` is a non-blocking alternative to
+`time.sleep`.
+
"""
from __future__ import absolute_import, division, print_function
class IOLoop(Configurable):
"""A level-triggered I/O loop.
- We use ``epoll`` (Linux) or ``kqueue`` (BSD and Mac OS X) if they
- are available, or else we fall back on select(). If you are
- implementing a system that needs to handle thousands of
- simultaneous connections, you should use a system that supports
- either ``epoll`` or ``kqueue``.
+ On Python 3, `IOLoop` is a wrapper around the `asyncio` event
+ loop. On Python 2, it uses ``epoll`` (Linux) or ``kqueue`` (BSD
+ and Mac OS X) if they are available, or else we fall back on
+ select(). If you are implementing a system that needs to handle
+ thousands of simultaneous connections, you should use a system
+ that supports either ``epoll`` or ``kqueue``.
Example usage for a simple TCP server:
.. versionchanged:: 4.2
Added the ``make_current`` keyword argument to the `IOLoop`
constructor.
+
+ .. versionchanged:: 5.0
+
+ Uses the `asyncio` event loop by default. The
+ ``IOLoop.configure`` method cannot be used on Python 3 except
+ to redundantly specify the `asyncio` event loop.
+
"""
# Constants from the epoll module
_EPOLLIN = 0x001
.. versionchanged:: 4.1
An `IOLoop` created while there is no current `IOLoop`
will automatically become current.
+
+ .. versionchanged:: 5.0
+ This method also sets the current `asyncio` event loop.
"""
IOLoop._current.instance = self
"""Clears the `IOLoop` for the current thread.
Intended primarily for use by test frameworks in between tests.
+
+ .. versionchanged:: 5.0
+ This method also clears the current `asyncio` event loop.
"""
old = IOLoop._current.instance
if old is not None:
documentation for the `signal` module for more information.
If ``action`` is None, the process will be killed if it is
blocked for too long.
+
+ .. deprecated:: 5.0
+
+ Not implemented on the `asyncio` event loop. Use the environment
+ variable ``PYTHONASYNCIODEBUG=1`` instead.
"""
raise NotImplementedError()
Equivalent to ``set_blocking_signal_threshold(seconds,
self.log_stack)``
+
+ .. deprecated:: 5.0
+
+ Not implemented on the `asyncio` event loop. Use the environment
+ variable ``PYTHONASYNCIODEBUG=1`` instead.
"""
self.set_blocking_signal_threshold(seconds, self.log_stack)
.. versionchanged:: 4.3
Returning a non-``None``, non-yieldable value is now an error.
+
+ .. versionchanged:: 5.0
+ If a timeout occurs, the ``func`` coroutine will be cancelled.
"""
future_cell = [None]
"""Runs a function in a ``concurrent.futures.Executor``. If
``executor`` is ``None``, the IO loop's default executor will be used.
- Use `functools.partial` to pass keyword arguments to `func`.
+ Use `functools.partial` to pass keyword arguments to ``func``.
+ .. versionadded:: 5.0
"""
if ThreadPoolExecutor is None:
raise RuntimeError(
return t_future
def set_default_executor(self, executor):
- """Sets the default executor to use with :meth:`run_in_executor`."""
+ """Sets the default executor to use with :meth:`run_in_executor`.
+
+ .. versionadded:: 5.0
+ """
self._executor = executor
def _run_callback(self, callback):
in Python 3.4. This makes it possible to combine the two libraries on
the same event loop.
-Most applications should use `AsyncIOMainLoop` to run Tornado on the
-default ``asyncio`` event loop. Applications that need to run event
-loops on multiple threads may use `AsyncIOLoop` to create multiple
-loops.
+.. deprecated:: 5.0
+
+ While the code in this module is still used, it is now enabled
+ automatically when `asyncio` is available, so applications should
+ no longer need to refer to this module directly.
.. note::
class AsyncIOMainLoop(BaseAsyncIOLoop):
"""``AsyncIOMainLoop`` creates an `.IOLoop` that corresponds to the
current ``asyncio`` event loop (i.e. the one returned by
- ``asyncio.get_event_loop()``). Recommended usage::
+ ``asyncio.get_event_loop()``).
- from tornado.platform.asyncio import AsyncIOMainLoop
- import asyncio
- AsyncIOMainLoop().install()
- asyncio.get_event_loop().run_forever()
+ .. deprecated:: 5.0
- See also :meth:`tornado.ioloop.IOLoop.install` for general notes on
- installing alternative IOLoops.
+ Now used automatically when appropriate; it is no longer necessary
+ to refer to this class directly.
"""
def initialize(self, **kwargs):
super(AsyncIOMainLoop, self).initialize(asyncio.get_event_loop(),
"""``AsyncIOLoop`` is an `.IOLoop` that runs on an ``asyncio`` event loop.
This class follows the usual Tornado semantics for creating new
``IOLoops``; these loops are not necessarily related to the
- ``asyncio`` default event loop. Recommended usage::
-
- from tornado.ioloop import IOLoop
- IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop')
- IOLoop.current().start()
+ ``asyncio`` default event loop.
Each ``AsyncIOLoop`` creates a new ``asyncio.EventLoop``; this object
can be accessed with the ``asyncio_loop`` attribute.
+
+ .. versionchanged:: 5.0
+
+ When an ``AsyncIOLoop`` becomes the current `.IOLoop`, it also sets
+ the current `asyncio` event loop.
+
+ .. deprecated:: 5.0
+
+ Now used automatically when appropriate; it is no longer necessary
+ to refer to this class directly.
"""
def initialize(self, **kwargs):
loop = asyncio.new_event_loop()
.. versionchanged:: 4.5
Added the ``source_ip`` and ``source_port`` arguments.
+
+ .. versionchanged:: 5.0
+ Added the ``timeout`` argument.
"""
if timeout is not None:
if isinstance(timeout, numbers.Real):
If the path begins with http:// or https://, it will be treated as a
full URL and will be fetched as-is.
+
+ .. versionchanged:: 5.0
+ Added support for absolute URLs.
"""
if path.lower().startswith(('http://', 'https://')):
self.http_client.fetch(path, self.stop, **kwargs)
Configurable subclasses must define the class methods
`configurable_base` and `configurable_default`, and use the instance
method `initialize` instead of ``__init__``.
+
+ .. versionchanged:: 5.0
+
+ It is now possible for configuration to be specified at
+ multiple levels of a class hierarchy.
+
"""
__impl_class = None # type: type
__impl_kwargs = None # type: Dict[str, Any]
def set_status(self, status_code, reason=None):
"""Sets the status code for our response.
- :arg int status_code: Response status code. If ``reason`` is ``None``,
- it must be present in `httplib.responses <http.client.responses>`.
+ :arg int status_code: Response status code.
:arg string reason: Human-readable reason phrase describing the status
code. If ``None``, it will be filled in from
- `httplib.responses <http.client.responses>`.
+ `http.client.responses` or "Unknown".
+
+ .. versionchanged:: 5.0
+
+ No longer validates that the response code is in
+ `http.client.responses`.
"""
self._status_code = status_code
if reason is not None:
.. versionchanged:: 4.5
Added support for substitutions into the destination URL.
+
+ .. versionchanged:: 5.0
+ If any query arguments are present, they will be copied to the
+ destination URL.
"""
def initialize(self, url, permanent=True):
self._url = url