From: Ben Darnell Date: Mon, 22 May 2017 03:57:46 +0000 (-0400) Subject: all: Remove deprecated io_loop arguments X-Git-Tag: v5.0.0~80^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=547e0f98d56bb8f22a89c009b6d2b3cf6b802284;p=thirdparty%2Ftornado.git all: Remove deprecated io_loop arguments IOLoop.current() is now used in all cases; it is no longer possible to pass IOLoops around and use them directly. This occasionally requires awkward workarounds with IOLoop.run_sync, but mainly in test code (and the synchronous HTTPClient). --- diff --git a/docs/httpclient.rst b/docs/httpclient.rst index 53a0a8812..782316180 100644 --- a/docs/httpclient.rst +++ b/docs/httpclient.rst @@ -47,7 +47,7 @@ Implementations .. module:: tornado.curl_httpclient -.. class:: CurlAsyncHTTPClient(io_loop, max_clients=10, defaults=None) +.. class:: CurlAsyncHTTPClient(max_clients=10, defaults=None) ``libcurl``-based HTTP client. diff --git a/tornado/autoreload.py b/tornado/autoreload.py index 60571efe7..24deb79d8 100644 --- a/tornado/autoreload.py +++ b/tornado/autoreload.py @@ -111,13 +111,13 @@ _reload_attempted = False _io_loops = weakref.WeakKeyDictionary() # type: ignore -def start(io_loop=None, check_time=500): +def start(check_time=500): """Begins watching source files for changes. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - io_loop = io_loop or ioloop.IOLoop.current() + io_loop = ioloop.IOLoop.current() if io_loop in _io_loops: return _io_loops[io_loop] = True @@ -125,7 +125,7 @@ def start(io_loop=None, check_time=500): gen_log.warning("tornado.autoreload started more than once in the same process") modify_times = {} callback = functools.partial(_reload_on_update, modify_times) - scheduler = ioloop.PeriodicCallback(callback, check_time, io_loop=io_loop) + scheduler = ioloop.PeriodicCallback(callback, check_time) scheduler.start() diff --git a/tornado/curl_httpclient.py b/tornado/curl_httpclient.py index 554710ee4..77c9537cb 100644 --- a/tornado/curl_httpclient.py +++ b/tornado/curl_httpclient.py @@ -37,8 +37,8 @@ curl_log = logging.getLogger('tornado.curl_httpclient') class CurlAsyncHTTPClient(AsyncHTTPClient): - def initialize(self, io_loop, max_clients=10, defaults=None): - super(CurlAsyncHTTPClient, self).initialize(io_loop, defaults=defaults) + def initialize(self, max_clients=10, defaults=None): + super(CurlAsyncHTTPClient, self).initialize(defaults=defaults) self._multi = pycurl.CurlMulti() self._multi.setopt(pycurl.M_TIMERFUNCTION, self._set_timeout) self._multi.setopt(pycurl.M_SOCKETFUNCTION, self._handle_socket) @@ -53,7 +53,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): # SOCKETFUNCTION. Mitigate the effects of such bugs by # forcing a periodic scan of all active requests. self._force_timeout_callback = ioloop.PeriodicCallback( - self._handle_force_timeout, 1000, io_loop=io_loop) + self._handle_force_timeout, 1000) self._force_timeout_callback.start() # Work around a bug in libcurl 7.29.0: Some fields in the curl diff --git a/tornado/gen.py b/tornado/gen.py index 99f910666..2e9e9a6a8 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -624,14 +624,14 @@ def Task(func, *args, **kwargs): class YieldFuture(YieldPoint): - def __init__(self, future, io_loop=None): + def __init__(self, future): """Adapts a `.Future` to the `YieldPoint` interface. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ self.future = future - self.io_loop = io_loop or IOLoop.current() + self.io_loop = IOLoop.current() def start(self, runner): if not self.future.done(): @@ -868,7 +868,7 @@ def maybe_future(x): return fut -def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): +def with_timeout(timeout, future, quiet_exceptions=()): """Wraps a `.Future` (or other yieldable object) in a timeout. Raises `TimeoutError` if the input future does not complete before @@ -902,8 +902,7 @@ def with_timeout(timeout, future, io_loop=None, quiet_exceptions=()): future = convert_yielded(future) result = Future() chain_future(future, result) - if io_loop is None: - io_loop = IOLoop.current() + io_loop = IOLoop.current() def error_callback(future): try: diff --git a/tornado/http1connection.py b/tornado/http1connection.py index 53744ece3..c6d3e336f 100644 --- a/tornado/http1connection.py +++ b/tornado/http1connection.py @@ -164,7 +164,6 @@ class HTTP1Connection(httputil.HTTPConnection): header_data = yield gen.with_timeout( self.stream.io_loop.time() + self.params.header_timeout, header_future, - io_loop=self.stream.io_loop, quiet_exceptions=iostream.StreamClosedError) except gen.TimeoutError: self.close() @@ -224,7 +223,7 @@ class HTTP1Connection(httputil.HTTPConnection): try: yield gen.with_timeout( self.stream.io_loop.time() + self._body_timeout, - body_future, self.stream.io_loop, + body_future, quiet_exceptions=iostream.StreamClosedError) except gen.TimeoutError: gen_log.info("Timeout reading body from %s", diff --git a/tornado/httpclient.py b/tornado/httpclient.py index 8436ece46..05c62081a 100644 --- a/tornado/httpclient.py +++ b/tornado/httpclient.py @@ -46,7 +46,7 @@ import weakref from tornado.concurrent import TracebackFuture from tornado.escape import utf8, native_str -from tornado import httputil, stack_context +from tornado import gen, httputil, stack_context from tornado.ioloop import IOLoop from tornado.util import Configurable @@ -75,7 +75,10 @@ class HTTPClient(object): self._io_loop = IOLoop(make_current=False) if async_client_class is None: async_client_class = AsyncHTTPClient - self._async_client = async_client_class(self._io_loop, **kwargs) + # Create the client while our IOLoop is "current", without + # clobbering the thread's real current IOLoop (if any). + self._async_client = self._io_loop.run_sync( + gen.coroutine(lambda: async_client_class(**kwargs))) self._closed = False def __del__(self): @@ -120,12 +123,12 @@ class AsyncHTTPClient(Configurable): The constructor for this class is magic in several respects: It actually creates an instance of an implementation-specific subclass, and instances are reused as a kind of pseudo-singleton - (one per `.IOLoop`). The keyword argument ``force_instance=True`` - can be used to suppress this singleton behavior. Unless - ``force_instance=True`` is used, no arguments other than - ``io_loop`` should be passed to the `AsyncHTTPClient` constructor. - The implementation subclass as well as arguments to its - constructor can be set with the static method `configure()` + (one per `.IOLoop`). The keyword argument ``force_instance=True`` + can be used to suppress this singleton behavior. Unless + ``force_instance=True`` is used, no arguments should be passed to + the `AsyncHTTPClient` constructor. The implementation subclass as + well as arguments to its constructor can be set with the static + method `configure()` All `AsyncHTTPClient` implementations support a ``defaults`` keyword argument, which can be used to set default values for @@ -137,8 +140,9 @@ class AsyncHTTPClient(Configurable): client = AsyncHTTPClient(force_instance=True, defaults=dict(user_agent="MyUserAgent")) - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. + """ @classmethod def configurable_base(cls): @@ -156,16 +160,15 @@ class AsyncHTTPClient(Configurable): setattr(cls, attr_name, weakref.WeakKeyDictionary()) return getattr(cls, attr_name) - def __new__(cls, io_loop=None, force_instance=False, **kwargs): - io_loop = io_loop or IOLoop.current() + def __new__(cls, force_instance=False, **kwargs): + io_loop = IOLoop.current() if force_instance: instance_cache = None else: instance_cache = cls._async_clients() if instance_cache is not None and io_loop in instance_cache: return instance_cache[io_loop] - instance = super(AsyncHTTPClient, cls).__new__(cls, io_loop=io_loop, - **kwargs) + instance = super(AsyncHTTPClient, cls).__new__(cls, **kwargs) # Make sure the instance knows which cache to remove itself from. # It can't simply call _async_clients() because we may be in # __new__(AsyncHTTPClient) but instance.__class__ may be @@ -175,8 +178,8 @@ class AsyncHTTPClient(Configurable): instance_cache[instance.io_loop] = instance return instance - def initialize(self, io_loop, defaults=None): - self.io_loop = io_loop + def initialize(self, defaults=None): + self.io_loop = IOLoop.current() self.defaults = dict(HTTPRequest._DEFAULTS) if defaults is not None: self.defaults.update(defaults) diff --git a/tornado/httpserver.py b/tornado/httpserver.py index d757be188..7a7d08cd2 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -134,6 +134,9 @@ class HTTPServer(TCPServer, Configurable, .. versionchanged:: 4.5 Added the ``trusted_downstream`` argument. + + .. versionchanged:: 5.0 + The ``io_loop`` argument has been removed. """ def __init__(self, *args, **kwargs): # Ignore args to __init__; real initialization belongs in @@ -143,7 +146,7 @@ class HTTPServer(TCPServer, Configurable, # completely) pass - def initialize(self, request_callback, no_keep_alive=False, io_loop=None, + def initialize(self, request_callback, no_keep_alive=False, xheaders=False, ssl_options=None, protocol=None, decompress_request=False, chunk_size=None, max_header_size=None, @@ -162,7 +165,7 @@ class HTTPServer(TCPServer, Configurable, max_body_size=max_body_size, body_timeout=body_timeout, no_keep_alive=no_keep_alive) - TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options, + TCPServer.__init__(self, ssl_options=ssl_options, max_buffer_size=max_buffer_size, read_chunk_size=chunk_size) self._connections = set() diff --git a/tornado/ioloop.py b/tornado/ioloop.py index a1288e775..5997cef66 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -1000,15 +1000,15 @@ class PeriodicCallback(object): `start` must be called after the `PeriodicCallback` is created. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def __init__(self, callback, callback_time, io_loop=None): + def __init__(self, callback, callback_time): self.callback = callback if callback_time <= 0: raise ValueError("Periodic callback must have a positive callback_time") self.callback_time = callback_time - self.io_loop = io_loop or IOLoop.current() + self.io_loop = IOLoop.current() self._running = False self._timeout = None diff --git a/tornado/iostream.py b/tornado/iostream.py index a1619c497..94249028b 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -135,12 +135,10 @@ class BaseIOStream(object): Subclasses must implement `fileno`, `close_fd`, `write_to_fd`, `read_from_fd`, and optionally `get_fd_error`. """ - def __init__(self, io_loop=None, max_buffer_size=None, + def __init__(self, max_buffer_size=None, read_chunk_size=None, max_write_buffer_size=None): """`BaseIOStream` constructor. - :arg io_loop: The `.IOLoop` to use; defaults to `.IOLoop.current`. - Deprecated since Tornado 4.1. :arg max_buffer_size: Maximum amount of incoming data to buffer; defaults to 100MB. :arg read_chunk_size: Amount of data to read at one time from the @@ -151,8 +149,11 @@ class BaseIOStream(object): .. versionchanged:: 4.0 Add the ``max_write_buffer_size`` parameter. Changed default ``read_chunk_size`` to 64KB. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been + removed. """ - self.io_loop = io_loop or ioloop.IOLoop.current() + self.io_loop = ioloop.IOLoop.current() self.max_buffer_size = max_buffer_size or 104857600 # A chunk size that is too close to max_buffer_size can cause # spurious failures. @@ -1186,8 +1187,7 @@ class IOStream(BaseIOStream): self._close_callback = None future = TracebackFuture() - ssl_stream = SSLIOStream(socket, ssl_options=ssl_options, - io_loop=self.io_loop) + ssl_stream = SSLIOStream(socket, ssl_options=ssl_options) # Wrap the original close callback so we can fail our Future as well. # If we had an "unwrap" counterpart to this method we would need # to restore the original callback after our Future resolves diff --git a/tornado/netutil.py b/tornado/netutil.py index c34c8c8bb..97f84f13b 100644 --- a/tornado/netutil.py +++ b/tornado/netutil.py @@ -232,7 +232,7 @@ if hasattr(socket, 'AF_UNIX'): return sock -def add_accept_handler(sock, callback, io_loop=None): +def add_accept_handler(sock, callback): """Adds an `.IOLoop` event handler to accept new connections on ``sock``. When a connection is accepted, ``callback(connection, address)`` will @@ -241,12 +241,9 @@ def add_accept_handler(sock, callback, io_loop=None): is different from the ``callback(fd, events)`` signature used for `.IOLoop` handlers. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - if io_loop is None: - io_loop = IOLoop.current() - def accept_handler(fd, events): # More connections may come in while we're handling callbacks; # to prevent starvation of other tasks we must limit the number @@ -274,7 +271,7 @@ def add_accept_handler(sock, callback, io_loop=None): continue raise callback(connection, address) - io_loop.add_handler(sock, accept_handler, IOLoop.READ) + IOLoop.current().add_handler(sock, accept_handler, IOLoop.READ) def is_valid_ip(ip): @@ -363,11 +360,11 @@ class ExecutorResolver(Resolver): ``close_resolver=False``; use this if you want to reuse the same executor elsewhere. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def initialize(self, io_loop=None, executor=None, close_executor=True): - self.io_loop = io_loop or IOLoop.current() + def initialize(self, executor=None, close_executor=True): + self.io_loop = IOLoop.current() if executor is not None: self.executor = executor self.close_executor = close_executor @@ -400,8 +397,8 @@ class BlockingResolver(ExecutorResolver): The `.IOLoop` will be blocked during the resolution, although the callback will not be run until the next `.IOLoop` iteration. """ - def initialize(self, io_loop=None): - super(BlockingResolver, self).initialize(io_loop=io_loop) + def initialize(self): + super(BlockingResolver, self).initialize() class ThreadedResolver(ExecutorResolver): @@ -423,10 +420,10 @@ class ThreadedResolver(ExecutorResolver): _threadpool = None # type: ignore _threadpool_pid = None # type: int - def initialize(self, io_loop=None, num_threads=10): + def initialize(self, num_threads=10): threadpool = ThreadedResolver._create_threadpool(num_threads) super(ThreadedResolver, self).initialize( - io_loop=io_loop, executor=threadpool, close_executor=False) + executor=threadpool, close_executor=False) @classmethod def _create_threadpool(cls, num_threads): diff --git a/tornado/platform/caresresolver.py b/tornado/platform/caresresolver.py index fd6e9d274..38247f7e6 100644 --- a/tornado/platform/caresresolver.py +++ b/tornado/platform/caresresolver.py @@ -19,11 +19,11 @@ class CaresResolver(Resolver): the default for ``tornado.simple_httpclient``, but other libraries may default to ``AF_UNSPEC``. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def initialize(self, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def initialize(self): + self.io_loop = IOLoop.current() self.channel = pycares.Channel(sock_state_cb=self._sock_state_cb) self.fds = {} diff --git a/tornado/platform/twisted.py b/tornado/platform/twisted.py index 0f9787e84..79608e5fb 100644 --- a/tornado/platform/twisted.py +++ b/tornado/platform/twisted.py @@ -112,7 +112,7 @@ class TornadoReactor(PosixReactorBase): instead of ``reactor.run()``. It is also possible to create a non-global reactor by calling - ``tornado.platform.twisted.TornadoReactor(io_loop)``. However, if + ``tornado.platform.twisted.TornadoReactor()``. However, if the `.IOLoop` and reactor are to be short-lived (such as those used in unit tests), additional cleanup may be required. Specifically, it is recommended to call:: @@ -122,13 +122,11 @@ class TornadoReactor(PosixReactorBase): before closing the `.IOLoop`. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def __init__(self, io_loop=None): - if not io_loop: - io_loop = tornado.ioloop.IOLoop.current() - self._io_loop = io_loop + def __init__(self): + self._io_loop = tornado.ioloop.IOLoop.current() self._readers = {} # map of reader objects to fd self._writers = {} # map of writer objects to fd self._fds = {} # a map of fd to a (reader, writer) tuple @@ -319,7 +317,9 @@ class _TestReactor(TornadoReactor): """ def __init__(self): # always use a new ioloop - super(_TestReactor, self).__init__(IOLoop()) + IOLoop(make_current=True) + super(_TestReactor, self).__init__() + IOLoop.clear_current() def listenTCP(self, port, factory, backlog=50, interface=''): # default to localhost to avoid firewall prompts on the mac @@ -335,7 +335,7 @@ class _TestReactor(TornadoReactor): port, protocol, interface=interface, maxPacketSize=maxPacketSize) -def install(io_loop=None): +def install(): """Install this package as the default Twisted reactor. ``install()`` must be called very early in the startup process, @@ -346,13 +346,11 @@ def install(io_loop=None): in multi-process mode, and an external process manager such as ``supervisord`` is recommended instead. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - if not io_loop: - io_loop = tornado.ioloop.IOLoop.current() - reactor = TornadoReactor(io_loop) + reactor = TornadoReactor() from twisted.internet.main import installReactor # type: ignore installReactor(reactor) return reactor @@ -526,14 +524,13 @@ class TwistedResolver(Resolver): Requires Twisted 12.1 or newer. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def initialize(self, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def initialize(self): # partial copy of twisted.names.client.createResolver, which doesn't # allow for a reactor to be passed in. - self.reactor = tornado.platform.twisted.TornadoReactor(io_loop) + self.reactor = tornado.platform.twisted.TornadoReactor() host_resolver = twisted.names.hosts.Resolver('/etc/hosts') cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor) diff --git a/tornado/process.py b/tornado/process.py index fae94f3c1..594913c6b 100644 --- a/tornado/process.py +++ b/tornado/process.py @@ -200,15 +200,14 @@ class Subprocess(object): * ``stdin``, ``stdout``, and ``stderr`` may have the value ``tornado.process.Subprocess.STREAM``, which will make the corresponding attribute of the resulting Subprocess a `.PipeIOStream`. - * A new keyword argument ``io_loop`` may be used to pass in an IOLoop. The ``Subprocess.STREAM`` option and the ``set_exit_callback`` and ``wait_for_exit`` methods do not work on Windows. There is therefore no reason to use this class instead of ``subprocess.Popen`` on that platform. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ STREAM = object() @@ -217,7 +216,7 @@ class Subprocess(object): _waiting = {} # type: ignore def __init__(self, *args, **kwargs): - self.io_loop = kwargs.pop('io_loop', None) or ioloop.IOLoop.current() + self.io_loop = ioloop.IOLoop.current() # All FDs we create should be closed on error; those in to_close # should be closed in the parent process on success. pipe_fds = [] @@ -227,19 +226,19 @@ class Subprocess(object): kwargs['stdin'] = in_r pipe_fds.extend((in_r, in_w)) to_close.append(in_r) - self.stdin = PipeIOStream(in_w, io_loop=self.io_loop) + self.stdin = PipeIOStream(in_w) if kwargs.get('stdout') is Subprocess.STREAM: out_r, out_w = _pipe_cloexec() kwargs['stdout'] = out_w pipe_fds.extend((out_r, out_w)) to_close.append(out_w) - self.stdout = PipeIOStream(out_r, io_loop=self.io_loop) + self.stdout = PipeIOStream(out_r) if kwargs.get('stderr') is Subprocess.STREAM: err_r, err_w = _pipe_cloexec() kwargs['stderr'] = err_w pipe_fds.extend((err_r, err_w)) to_close.append(err_w) - self.stderr = PipeIOStream(err_r, io_loop=self.io_loop) + self.stderr = PipeIOStream(err_r) try: self.proc = subprocess.Popen(*args, **kwargs) except: @@ -270,7 +269,7 @@ class Subprocess(object): signal handler is causing a problem. """ self._exit_callback = stack_context.wrap(callback) - Subprocess.initialize(self.io_loop) + Subprocess.initialize() Subprocess._waiting[self.pid] = self Subprocess._try_cleanup_process(self.pid) @@ -302,7 +301,7 @@ class Subprocess(object): return future @classmethod - def initialize(cls, io_loop=None): + def initialize(cls): """Initializes the ``SIGCHLD`` handler. The signal handler is run on an `.IOLoop` to avoid locking issues. @@ -310,13 +309,13 @@ class Subprocess(object): same one used by individual Subprocess objects (as long as the ``IOLoops`` are each running in separate threads). - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been + removed. """ if cls._initialized: return - if io_loop is None: - io_loop = ioloop.IOLoop.current() + io_loop = ioloop.IOLoop.current() cls._old_sigchld = signal.signal( signal.SIGCHLD, lambda sig, frame: io_loop.add_callback_from_signal(cls._cleanup)) diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 8fb70707f..f394689d1 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -6,6 +6,7 @@ from tornado import gen from tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy from tornado import httputil from tornado.http1connection import HTTP1Connection, HTTP1ConnectionParameters +from tornado.ioloop import IOLoop from tornado.iostream import StreamClosedError from tornado.netutil import Resolver, OverrideResolver, _client_ssl_defaults from tornado.log import gen_log @@ -56,7 +57,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): are not reused, and callers cannot select the network interface to be used. """ - def initialize(self, io_loop, max_clients=10, + def initialize(self, max_clients=10, hostname_mapping=None, max_buffer_size=104857600, resolver=None, defaults=None, max_header_size=None, max_body_size=None): @@ -92,8 +93,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): .. versionchanged:: 4.2 Added the ``max_body_size`` argument. """ - super(SimpleAsyncHTTPClient, self).initialize(io_loop, - defaults=defaults) + super(SimpleAsyncHTTPClient, self).initialize(defaults=defaults) self.max_clients = max_clients self.queue = collections.deque() self.active = {} @@ -107,12 +107,12 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): self.resolver = resolver self.own_resolver = False else: - self.resolver = Resolver(io_loop=io_loop) + self.resolver = Resolver() self.own_resolver = True if hostname_mapping is not None: self.resolver = OverrideResolver(resolver=self.resolver, mapping=hostname_mapping) - self.tcp_client = TCPClient(resolver=self.resolver, io_loop=io_loop) + self.tcp_client = TCPClient(resolver=self.resolver) def close(self): super(SimpleAsyncHTTPClient, self).close() @@ -153,7 +153,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): def _handle_request(self, request, release_callback, final_callback): self._connection_class()( - self.io_loop, self, request, release_callback, + self, request, release_callback, final_callback, self.max_buffer_size, self.tcp_client, self.max_header_size, self.max_body_size) @@ -190,11 +190,11 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient): class _HTTPConnection(httputil.HTTPMessageDelegate): _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]) - def __init__(self, io_loop, client, request, release_callback, + def __init__(self, client, request, release_callback, final_callback, max_buffer_size, tcp_client, max_header_size, max_body_size): - self.start_time = io_loop.time() - self.io_loop = io_loop + self.io_loop = IOLoop.current() + self.start_time = self.io_loop.time() self.client = client self.request = request self.release_callback = release_callback diff --git a/tornado/tcpclient.py b/tornado/tcpclient.py index 33074bd58..ec51a6134 100644 --- a/tornado/tcpclient.py +++ b/tornado/tcpclient.py @@ -47,8 +47,8 @@ class _Connector(object): http://tools.ietf.org/html/rfc6555 """ - def __init__(self, addrinfo, io_loop, connect): - self.io_loop = io_loop + def __init__(self, addrinfo, connect): + self.io_loop = IOLoop.current() self.connect = connect self.future = Future() @@ -137,16 +137,15 @@ class _Connector(object): class TCPClient(object): """A non-blocking TCP connection factory. - .. versionchanged:: 4.1 - The ``io_loop`` argument is deprecated. + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - def __init__(self, resolver=None, io_loop=None): - self.io_loop = io_loop or IOLoop.current() + def __init__(self, resolver=None): if resolver is not None: self.resolver = resolver self._own_resolver = False else: - self.resolver = Resolver(io_loop=io_loop) + self.resolver = Resolver() self._own_resolver = True def close(self): @@ -175,7 +174,7 @@ class TCPClient(object): """ addrinfo = yield self.resolver.resolve(host, port, af) connector = _Connector( - addrinfo, self.io_loop, + addrinfo, functools.partial(self._create_stream, max_buffer_size, source_ip=source_ip, source_port=source_port) ) @@ -212,7 +211,6 @@ class TCPClient(object): raise try: stream = IOStream(socket_obj, - io_loop=self.io_loop, max_buffer_size=max_buffer_size) except socket.error as e: fu = Future() diff --git a/tornado/tcpserver.py b/tornado/tcpserver.py index f47ec89a4..b3cdaa2ca 100644 --- a/tornado/tcpserver.py +++ b/tornado/tcpserver.py @@ -102,10 +102,13 @@ class TCPServer(object): .. versionadded:: 3.1 The ``max_buffer_size`` argument. + + .. versionchanged:: 5.0 + The ``io_loop`` argument has been removed. """ - def __init__(self, io_loop=None, ssl_options=None, max_buffer_size=None, + def __init__(self, ssl_options=None, max_buffer_size=None, read_chunk_size=None): - self.io_loop = io_loop + self.io_loop = IOLoop.current() self.ssl_options = ssl_options self._sockets = {} # fd -> socket object self._pending_sockets = [] @@ -151,13 +154,9 @@ class TCPServer(object): method and `tornado.process.fork_processes` to provide greater control over the initialization of a multi-process server. """ - if self.io_loop is None: - self.io_loop = IOLoop.current() - for sock in sockets: self._sockets[sock.fileno()] = sock - add_accept_handler(sock, self._handle_connection, - io_loop=self.io_loop) + add_accept_handler(sock, self._handle_connection) def add_socket(self, socket): """Singular version of `add_sockets`. Takes a single socket object.""" @@ -284,11 +283,11 @@ class TCPServer(object): raise try: if self.ssl_options is not None: - stream = SSLIOStream(connection, io_loop=self.io_loop, + stream = SSLIOStream(connection, max_buffer_size=self.max_buffer_size, read_chunk_size=self.read_chunk_size) else: - stream = IOStream(connection, io_loop=self.io_loop, + stream = IOStream(connection, max_buffer_size=self.max_buffer_size, read_chunk_size=self.read_chunk_size) diff --git a/tornado/test/concurrent_test.py b/tornado/test/concurrent_test.py index 4d89f5723..e20281fc3 100644 --- a/tornado/test/concurrent_test.py +++ b/tornado/test/concurrent_test.py @@ -25,6 +25,7 @@ import traceback from tornado.concurrent import Future, return_future, ReturnValueIgnoredError, run_on_executor from tornado.escape import utf8, to_unicode from tornado import gen +from tornado.ioloop import IOLoop from tornado.iostream import IOStream from tornado.log import app_log from tornado import stack_context @@ -217,9 +218,8 @@ class CapError(Exception): class BaseCapClient(object): - def __init__(self, port, io_loop): + def __init__(self, port): self.port = port - self.io_loop = io_loop def process_response(self, data): status, message = re.match('(.*)\t(.*)\n', to_unicode(data)).groups() @@ -233,7 +233,7 @@ class ManualCapClient(BaseCapClient): def capitalize(self, request_data, callback=None): logging.info("capitalize") self.request_data = request_data - self.stream = IOStream(socket.socket(), io_loop=self.io_loop) + self.stream = IOStream(socket.socket()) self.stream.connect(('127.0.0.1', self.port), callback=self.handle_connect) self.future = Future() @@ -261,7 +261,7 @@ class DecoratorCapClient(BaseCapClient): def capitalize(self, request_data, callback): logging.info("capitalize") self.request_data = request_data - self.stream = IOStream(socket.socket(), io_loop=self.io_loop) + self.stream = IOStream(socket.socket()) self.stream.connect(('127.0.0.1', self.port), callback=self.handle_connect) self.callback = callback @@ -282,7 +282,7 @@ class GeneratorCapClient(BaseCapClient): @gen.engine def capitalize(self, request_data, callback): logging.info('capitalize') - stream = IOStream(socket.socket(), io_loop=self.io_loop) + stream = IOStream(socket.socket()) logging.info('connecting') yield gen.Task(stream.connect, ('127.0.0.1', self.port)) stream.write(utf8(request_data + '\n')) @@ -296,10 +296,10 @@ class GeneratorCapClient(BaseCapClient): class ClientTestMixin(object): def setUp(self): super(ClientTestMixin, self).setUp() # type: ignore - self.server = CapServer(io_loop=self.io_loop) + self.server = CapServer() sock, port = bind_unused_port() self.server.add_sockets([sock]) - self.client = self.client_class(io_loop=self.io_loop, port=port) + self.client = self.client_class(port=port) def tearDown(self): self.server.stop() diff --git a/tornado/test/curl_httpclient_test.py b/tornado/test/curl_httpclient_test.py index eb6f89d66..35d75011c 100644 --- a/tornado/test/curl_httpclient_test.py +++ b/tornado/test/curl_httpclient_test.py @@ -24,8 +24,7 @@ if pycurl is not None: @unittest.skipIf(pycurl is None, "pycurl module not present") class CurlHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase): def get_http_client(self): - client = CurlAsyncHTTPClient(io_loop=self.io_loop, - defaults=dict(allow_ipv6=False)) + client = CurlAsyncHTTPClient(defaults=dict(allow_ipv6=False)) # make sure AsyncHTTPClient magic doesn't give us the wrong class self.assertTrue(isinstance(client, CurlAsyncHTTPClient)) return client @@ -94,7 +93,7 @@ class CurlHTTPClientTestCase(AsyncHTTPTestCase): ]) def create_client(self, **kwargs): - return CurlAsyncHTTPClient(self.io_loop, force_instance=True, + return CurlAsyncHTTPClient(force_instance=True, defaults=dict(allow_ipv6=False), **kwargs) diff --git a/tornado/test/gen_test.py b/tornado/test/gen_test.py index fea4c6449..8183c164e 100644 --- a/tornado/test/gen_test.py +++ b/tornado/test/gen_test.py @@ -1096,8 +1096,7 @@ class GenTaskHandler(RequestHandler): @asynchronous @gen.engine def get(self): - io_loop = self.request.connection.stream.io_loop - client = AsyncHTTPClient(io_loop=io_loop) + client = AsyncHTTPClient() response = yield gen.Task(client.fetch, self.get_argument('url')) response.rethrow() self.finish(b"got response: " + response.body) @@ -1250,7 +1249,7 @@ class WithTimeoutTest(AsyncTestCase): self.io_loop.add_timeout(datetime.timedelta(seconds=0.1), lambda: future.set_result('asdf')) result = yield gen.with_timeout(datetime.timedelta(seconds=3600), - future, io_loop=self.io_loop) + future) self.assertEqual(result, 'asdf') @gen_test @@ -1261,14 +1260,14 @@ class WithTimeoutTest(AsyncTestCase): lambda: future.set_exception(ZeroDivisionError())) with self.assertRaises(ZeroDivisionError): yield gen.with_timeout(datetime.timedelta(seconds=3600), - future, io_loop=self.io_loop) + future) @gen_test def test_already_resolved(self): future = Future() future.set_result('asdf') result = yield gen.with_timeout(datetime.timedelta(seconds=3600), - future, io_loop=self.io_loop) + future) self.assertEqual(result, 'asdf') @unittest.skipIf(futures is None, 'futures module not present') diff --git a/tornado/test/httpclient_test.py b/tornado/test/httpclient_test.py index 320454e41..1fa42b7ee 100644 --- a/tornado/test/httpclient_test.py +++ b/tornado/test/httpclient_test.py @@ -210,10 +210,10 @@ Transfer-Encoding: chunked def accept_callback(conn, address): # fake an HTTP server using chunked encoding where the final chunks # and connection close all happen at once - stream = IOStream(conn, io_loop=self.io_loop) + stream = IOStream(conn) stream.read_until(b"\r\n\r\n", functools.partial(write_response, stream)) - netutil.add_accept_handler(sock, accept_callback, self.io_loop) + netutil.add_accept_handler(sock, accept_callback) self.http_client.fetch("http://127.0.0.1:%d/" % port, self.stop) resp = self.wait() resp.rethrow() @@ -358,7 +358,7 @@ Transfer-Encoding: chunked def test_configure_defaults(self): defaults = dict(user_agent='TestDefaultUserAgent', allow_ipv6=False) # Construct a new instance of the configured client class - client = self.http_client.__class__(self.io_loop, force_instance=True, + client = self.http_client.__class__(force_instance=True, defaults=defaults) try: client.fetch(self.get_url('/user_agent'), callback=self.stop) @@ -398,10 +398,10 @@ X-XSS-Protection: 1; """.replace(b"\n", b"\r\n"), callback=stream.close) def accept_callback(conn, address): - stream = IOStream(conn, io_loop=self.io_loop) + stream = IOStream(conn) stream.read_until(b"\r\n\r\n", functools.partial(write_response, stream)) - netutil.add_accept_handler(sock, accept_callback, self.io_loop) + netutil.add_accept_handler(sock, accept_callback) self.http_client.fetch("http://127.0.0.1:%d/" % port, self.stop) resp = self.wait() resp.rethrow() @@ -594,10 +594,13 @@ class SyncHTTPClientTest(unittest.TestCase): 'AsyncIOMainLoop') self.server_ioloop = IOLoop() - sock, self.port = bind_unused_port() - app = Application([('/', HelloWorldHandler)]) - self.server = HTTPServer(app, io_loop=self.server_ioloop) - self.server.add_socket(sock) + @gen.coroutine + def init_server(): + sock, self.port = bind_unused_port() + app = Application([('/', HelloWorldHandler)]) + self.server = HTTPServer(app) + self.server.add_socket(sock) + self.server_ioloop.run_sync(init_server) self.server_thread = threading.Thread(target=self.server_ioloop.start) self.server_thread.start() diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 11cb72313..f5f91a9df 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -256,7 +256,7 @@ class HTTPConnectionTest(AsyncHTTPTestCase): # Run through a 100-continue interaction by hand: # When given Expect: 100-continue, we get a 100 response after the # headers, and then the real response after the body. - stream = IOStream(socket.socket(), io_loop=self.io_loop) + stream = IOStream(socket.socket()) stream.connect(("127.0.0.1", self.get_http_port()), callback=self.stop) self.wait() stream.write(b"\r\n".join([b"POST /hello HTTP/1.1", @@ -597,9 +597,9 @@ class UnixSocketTest(AsyncTestCase): self.sockfile = os.path.join(self.tmpdir, "test.sock") sock = netutil.bind_unix_socket(self.sockfile) app = Application([("/hello", HelloWorldRequestHandler)]) - self.server = HTTPServer(app, io_loop=self.io_loop) + self.server = HTTPServer(app) self.server.add_socket(sock) - self.stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop) + self.stream = IOStream(socket.socket(socket.AF_UNIX)) self.stream.connect(self.sockfile, self.stop) self.wait() @@ -681,7 +681,7 @@ class KeepAliveTest(AsyncHTTPTestCase): # The next few methods are a crude manual http client def connect(self): - self.stream = IOStream(socket.socket(), io_loop=self.io_loop) + self.stream = IOStream(socket.socket()) self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop) self.wait() @@ -842,7 +842,7 @@ class StreamingChunkSizeTest(AsyncHTTPTestCase): def get_http_client(self): # body_producer doesn't work on curl_httpclient, so override the # configured AsyncHTTPClient implementation. - return SimpleAsyncHTTPClient(io_loop=self.io_loop) + return SimpleAsyncHTTPClient() def get_httpserver_options(self): return dict(chunk_size=self.CHUNK_SIZE, decompress_request=True) @@ -1025,7 +1025,7 @@ class BodyLimitsTest(AsyncHTTPTestCase): def get_http_client(self): # body_producer doesn't work on curl_httpclient, so override the # configured AsyncHTTPClient implementation. - return SimpleAsyncHTTPClient(io_loop=self.io_loop) + return SimpleAsyncHTTPClient() def test_small_body(self): response = self.fetch('/buffered', method='PUT', body=b'a' * 4096) diff --git a/tornado/test/iostream_test.py b/tornado/test/iostream_test.py index 91bc7bf6a..030164479 100644 --- a/tornado/test/iostream_test.py +++ b/tornado/test/iostream_test.py @@ -185,8 +185,7 @@ class TestIOStreamMixin(object): def connect_callback(): streams[1] = client_stream self.stop() - netutil.add_accept_handler(listener, accept_callback, - io_loop=self.io_loop) + netutil.add_accept_handler(listener, accept_callback) client_stream = self._make_client_iostream(socket.socket(), **kwargs) client_stream.connect(('127.0.0.1', port), callback=connect_callback) @@ -227,7 +226,7 @@ class TestIOStreamMixin(object): # epoll IOLoop in this respect) cleanup_func, port = refusing_port() self.addCleanup(cleanup_func) - stream = IOStream(socket.socket(), self.io_loop) + stream = IOStream(socket.socket()) self.connect_called = False def connect_callback(): @@ -255,7 +254,7 @@ class TestIOStreamMixin(object): # so we mock it instead. If IOStream changes to call a Resolver # before sock.connect, the mock target will need to change too. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) - stream = IOStream(s, io_loop=self.io_loop) + stream = IOStream(s) stream.set_close_callback(self.stop) with mock.patch('socket.socket.connect', side_effect=socket.gaierror(errno.EIO, 'boom')): @@ -845,12 +844,12 @@ class TestIOStreamMixin(object): class TestIOStreamWebHTTP(TestIOStreamWebMixin, AsyncHTTPTestCase): def _make_client_iostream(self): - return IOStream(socket.socket(), io_loop=self.io_loop) + return IOStream(socket.socket()) class TestIOStreamWebHTTPS(TestIOStreamWebMixin, AsyncHTTPSTestCase): def _make_client_iostream(self): - return SSLIOStream(socket.socket(), io_loop=self.io_loop, + return SSLIOStream(socket.socket(), ssl_options=dict(cert_reqs=ssl.CERT_NONE)) @@ -868,10 +867,10 @@ class TestIOStreamSSL(TestIOStreamMixin, AsyncTestCase): server_side=True, do_handshake_on_connect=False, **_server_ssl_options()) - return SSLIOStream(connection, io_loop=self.io_loop, **kwargs) + return SSLIOStream(connection, **kwargs) def _make_client_iostream(self, connection, **kwargs): - return SSLIOStream(connection, io_loop=self.io_loop, + return SSLIOStream(connection, ssl_options=dict(cert_reqs=ssl.CERT_NONE), **kwargs) @@ -889,12 +888,11 @@ class TestIOStreamSSLContext(TestIOStreamMixin, AsyncTestCase): connection = ssl_wrap_socket(connection, context, server_side=True, do_handshake_on_connect=False) - return SSLIOStream(connection, io_loop=self.io_loop, **kwargs) + return SSLIOStream(connection, **kwargs) def _make_client_iostream(self, connection, **kwargs): context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - return SSLIOStream(connection, io_loop=self.io_loop, - ssl_options=context, **kwargs) + return SSLIOStream(connection, ssl_options=context, **kwargs) class TestIOStreamStartTLS(AsyncTestCase): @@ -1100,8 +1098,8 @@ class TestPipeIOStream(AsyncTestCase): def test_pipe_iostream(self): r, w = os.pipe() - rs = PipeIOStream(r, io_loop=self.io_loop) - ws = PipeIOStream(w, io_loop=self.io_loop) + rs = PipeIOStream(r) + ws = PipeIOStream(w) ws.write(b"hel") ws.write(b"lo world") @@ -1125,8 +1123,8 @@ class TestPipeIOStream(AsyncTestCase): def test_pipe_iostream_big_write(self): r, w = os.pipe() - rs = PipeIOStream(r, io_loop=self.io_loop) - ws = PipeIOStream(w, io_loop=self.io_loop) + rs = PipeIOStream(r) + ws = PipeIOStream(w) NUM_BYTES = 1048576 diff --git a/tornado/test/netutil_test.py b/tornado/test/netutil_test.py index 9564290ab..be581764b 100644 --- a/tornado/test/netutil_test.py +++ b/tornado/test/netutil_test.py @@ -78,7 +78,7 @@ def _failing_getaddrinfo(*args): class BlockingResolverTest(AsyncTestCase, _ResolverTestMixin): def setUp(self): super(BlockingResolverTest, self).setUp() - self.resolver = BlockingResolver(io_loop=self.io_loop) + self.resolver = BlockingResolver() # getaddrinfo-based tests need mocking to reliably generate errors; @@ -87,7 +87,7 @@ class BlockingResolverTest(AsyncTestCase, _ResolverTestMixin): class BlockingResolverErrorTest(AsyncTestCase, _ResolverErrorTestMixin): def setUp(self): super(BlockingResolverErrorTest, self).setUp() - self.resolver = BlockingResolver(io_loop=self.io_loop) + self.resolver = BlockingResolver() self.real_getaddrinfo = socket.getaddrinfo socket.getaddrinfo = _failing_getaddrinfo @@ -101,7 +101,7 @@ class BlockingResolverErrorTest(AsyncTestCase, _ResolverErrorTestMixin): class ThreadedResolverTest(AsyncTestCase, _ResolverTestMixin): def setUp(self): super(ThreadedResolverTest, self).setUp() - self.resolver = ThreadedResolver(io_loop=self.io_loop) + self.resolver = ThreadedResolver() def tearDown(self): self.resolver.close() @@ -111,7 +111,7 @@ class ThreadedResolverTest(AsyncTestCase, _ResolverTestMixin): class ThreadedResolverErrorTest(AsyncTestCase, _ResolverErrorTestMixin): def setUp(self): super(ThreadedResolverErrorTest, self).setUp() - self.resolver = BlockingResolver(io_loop=self.io_loop) + self.resolver = BlockingResolver() self.real_getaddrinfo = socket.getaddrinfo socket.getaddrinfo = _failing_getaddrinfo @@ -158,7 +158,7 @@ class ThreadedResolverImportTest(unittest.TestCase): class CaresResolverTest(AsyncTestCase, _ResolverTestMixin): def setUp(self): super(CaresResolverTest, self).setUp() - self.resolver = CaresResolver(io_loop=self.io_loop) + self.resolver = CaresResolver() # TwistedResolver produces consistent errors in our test cases so we @@ -170,7 +170,7 @@ class TwistedResolverTest(AsyncTestCase, _ResolverTestMixin, _ResolverErrorTestMixin): def setUp(self): super(TwistedResolverTest, self).setUp() - self.resolver = TwistedResolver(io_loop=self.io_loop) + self.resolver = TwistedResolver() class IsValidIPTest(unittest.TestCase): diff --git a/tornado/test/process_test.py b/tornado/test/process_test.py index 74c10abf1..d8337f5d5 100644 --- a/tornado/test/process_test.py +++ b/tornado/test/process_test.py @@ -147,8 +147,7 @@ class SubprocessTest(AsyncTestCase): "LayeredTwistedIOLoop") subproc = Subprocess([sys.executable, '-u', '-i'], stdin=Subprocess.STREAM, - stdout=Subprocess.STREAM, stderr=subprocess.STDOUT, - io_loop=self.io_loop) + stdout=Subprocess.STREAM, stderr=subprocess.STDOUT) self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait())) subproc.stdout.read_until(b'>>> ', self.stop) self.wait() @@ -168,8 +167,7 @@ class SubprocessTest(AsyncTestCase): # Close the parent's stdin handle and see that the child recognizes it. subproc = Subprocess([sys.executable, '-u', '-i'], stdin=Subprocess.STREAM, - stdout=Subprocess.STREAM, stderr=subprocess.STDOUT, - io_loop=self.io_loop) + stdout=Subprocess.STREAM, stderr=subprocess.STDOUT) self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait())) subproc.stdout.read_until(b'>>> ', self.stop) self.wait() @@ -184,8 +182,7 @@ class SubprocessTest(AsyncTestCase): skip_if_twisted() subproc = Subprocess([sys.executable, '-u', '-c', r"import sys; sys.stderr.write('hello\n')"], - stderr=Subprocess.STREAM, - io_loop=self.io_loop) + stderr=Subprocess.STREAM) self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait())) subproc.stderr.read_until(b'\n', self.stop) data = self.wait() @@ -194,10 +191,9 @@ class SubprocessTest(AsyncTestCase): def test_sigchild(self): # Twisted's SIGCHLD handler and Subprocess's conflict with each other. skip_if_twisted() - Subprocess.initialize(io_loop=self.io_loop) + Subprocess.initialize() self.addCleanup(Subprocess.uninitialize) - subproc = Subprocess([sys.executable, '-c', 'pass'], - io_loop=self.io_loop) + subproc = Subprocess([sys.executable, '-c', 'pass']) subproc.set_exit_callback(self.stop) ret = self.wait() self.assertEqual(ret, 0) @@ -215,12 +211,11 @@ class SubprocessTest(AsyncTestCase): def test_sigchild_signal(self): skip_if_twisted() - Subprocess.initialize(io_loop=self.io_loop) + Subprocess.initialize() self.addCleanup(Subprocess.uninitialize) subproc = Subprocess([sys.executable, '-c', 'import time; time.sleep(30)'], - stdout=Subprocess.STREAM, - io_loop=self.io_loop) + stdout=Subprocess.STREAM) subproc.set_exit_callback(self.stop) os.kill(subproc.pid, signal.SIGTERM) try: diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index 02d57c5fb..f71331431 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -29,8 +29,7 @@ from tornado.web import RequestHandler, Application, asynchronous, url, stream_r class SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase): def get_http_client(self): - client = SimpleAsyncHTTPClient(io_loop=self.io_loop, - force_instance=True) + client = SimpleAsyncHTTPClient(force_instance=True) self.assertTrue(isinstance(client, SimpleAsyncHTTPClient)) return client @@ -150,16 +149,16 @@ class SimpleHTTPClientTestMixin(object): def test_singleton(self): # Class "constructor" reuses objects on the same IOLoop - self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is - SimpleAsyncHTTPClient(self.io_loop)) + self.assertTrue(SimpleAsyncHTTPClient() is + SimpleAsyncHTTPClient()) # unless force_instance is used - self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not - SimpleAsyncHTTPClient(self.io_loop, - force_instance=True)) + self.assertTrue(SimpleAsyncHTTPClient() is not + SimpleAsyncHTTPClient(force_instance=True)) # different IOLoops use different objects with closing(IOLoop()) as io_loop2: - self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not - SimpleAsyncHTTPClient(io_loop2)) + client1 = self.io_loop.run_sync(gen.coroutine(SimpleAsyncHTTPClient)) + client2 = io_loop2.run_sync(gen.coroutine(SimpleAsyncHTTPClient)) + self.assertTrue(client1 is not client2) def test_connection_limit(self): with closing(self.create_client(max_clients=2)) as client: @@ -481,8 +480,7 @@ class SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase): self.http_client = self.create_client() def create_client(self, **kwargs): - return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, - **kwargs) + return SimpleAsyncHTTPClient(force_instance=True, **kwargs) class SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase): @@ -491,7 +489,7 @@ class SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase): self.http_client = self.create_client() def create_client(self, **kwargs): - return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, + return SimpleAsyncHTTPClient(force_instance=True, defaults=dict(validate_cert=False), **kwargs) @@ -544,24 +542,22 @@ class CreateAsyncHTTPClientTestCase(AsyncTestCase): def test_max_clients(self): AsyncHTTPClient.configure(SimpleAsyncHTTPClient) - with closing(AsyncHTTPClient( - self.io_loop, force_instance=True)) as client: + with closing(AsyncHTTPClient(force_instance=True)) as client: self.assertEqual(client.max_clients, 10) with closing(AsyncHTTPClient( - self.io_loop, max_clients=11, force_instance=True)) as client: + max_clients=11, force_instance=True)) as client: self.assertEqual(client.max_clients, 11) # Now configure max_clients statically and try overriding it # with each way max_clients can be passed AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12) - with closing(AsyncHTTPClient( - self.io_loop, force_instance=True)) as client: + with closing(AsyncHTTPClient(force_instance=True)) as client: self.assertEqual(client.max_clients, 12) with closing(AsyncHTTPClient( - self.io_loop, max_clients=13, force_instance=True)) as client: + max_clients=13, force_instance=True)) as client: self.assertEqual(client.max_clients, 13) with closing(AsyncHTTPClient( - self.io_loop, max_clients=14, force_instance=True)) as client: + max_clients=14, force_instance=True)) as client: self.assertEqual(client.max_clients, 14) @@ -644,7 +640,6 @@ class HostnameMappingTestCase(AsyncHTTPTestCase): def setUp(self): super(HostnameMappingTestCase, self).setUp() self.http_client = SimpleAsyncHTTPClient( - self.io_loop, hostname_mapping={ 'www.example.com': '127.0.0.1', ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()), @@ -676,7 +671,6 @@ class ResolveTimeoutTestCase(AsyncHTTPTestCase): super(ResolveTimeoutTestCase, self).setUp() self.http_client = SimpleAsyncHTTPClient( - self.io_loop, resolver=BadResolver()) def get_app(self): @@ -703,7 +697,7 @@ class MaxHeaderSizeTest(AsyncHTTPTestCase): ('/large', LargeHeaders)]) def get_http_client(self): - return SimpleAsyncHTTPClient(io_loop=self.io_loop, max_header_size=1024) + return SimpleAsyncHTTPClient(max_header_size=1024) def test_small_headers(self): response = self.fetch('/small') @@ -730,7 +724,7 @@ class MaxBodySizeTest(AsyncHTTPTestCase): ('/large', LargeBody)]) def get_http_client(self): - return SimpleAsyncHTTPClient(io_loop=self.io_loop, max_body_size=1024 * 64) + return SimpleAsyncHTTPClient(max_body_size=1024 * 64) def test_small_body(self): response = self.fetch('/small') @@ -754,7 +748,7 @@ class MaxBufferSizeTest(AsyncHTTPTestCase): def get_http_client(self): # 100KB body with 64KB buffer - return SimpleAsyncHTTPClient(io_loop=self.io_loop, max_body_size=1024 * 100, max_buffer_size=1024 * 64) + return SimpleAsyncHTTPClient(max_body_size=1024 * 100, max_buffer_size=1024 * 64) def test_large_body(self): response = self.fetch('/large') diff --git a/tornado/test/stack_context_test.py b/tornado/test/stack_context_test.py index 59d25474c..fb9e0d7ac 100644 --- a/tornado/test/stack_context_test.py +++ b/tornado/test/stack_context_test.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function from tornado import gen +from tornado.ioloop import IOLoop from tornado.log import app_log from tornado.stack_context import (StackContext, wrap, NullContext, StackContextInconsistentError, ExceptionStackContext, run_with_stack_context, _state) @@ -14,22 +15,21 @@ import logging class TestRequestHandler(RequestHandler): - def __init__(self, app, request, io_loop): + def __init__(self, app, request): super(TestRequestHandler, self).__init__(app, request) - self.io_loop = io_loop @asynchronous def get(self): logging.debug('in get()') # call self.part2 without a self.async_callback wrapper. Its # exception should still get thrown - self.io_loop.add_callback(self.part2) + IOLoop.current().add_callback(self.part2) def part2(self): logging.debug('in part2()') # Go through a third layer to make sure that contexts once restored # are again passed on to future callbacks - self.io_loop.add_callback(self.part3) + IOLoop.current().add_callback(self.part3) def part3(self): logging.debug('in part3()') @@ -44,8 +44,7 @@ class TestRequestHandler(RequestHandler): class HTTPStackContextTest(AsyncHTTPTestCase): def get_app(self): - return Application([('/', TestRequestHandler, - dict(io_loop=self.io_loop))]) + return Application([('/', TestRequestHandler)]) def test_stack_context(self): with ExpectLog(app_log, "Uncaught exception GET /"): diff --git a/tornado/test/tcpclient_test.py b/tornado/test/tcpclient_test.py index 76206e85e..117f28de1 100644 --- a/tornado/test/tcpclient_test.py +++ b/tornado/test/tcpclient_test.py @@ -218,7 +218,7 @@ class ConnectorTest(AsyncTestCase): future.set_exception(IOError()) def start_connect(self, addrinfo): - conn = _Connector(addrinfo, self.io_loop, self.create_stream) + conn = _Connector(addrinfo, self.create_stream) # Give it a huge timeout; we'll trigger timeouts manually. future = conn.start(3600) return conn, future diff --git a/tornado/test/twisted_test.py b/tornado/test/twisted_test.py index 1604ce52f..10afebb7b 100644 --- a/tornado/test/twisted_test.py +++ b/tornado/test/twisted_test.py @@ -98,8 +98,9 @@ def restore_signal_handlers(saved): class ReactorTestCase(unittest.TestCase): def setUp(self): self._saved_signals = save_signal_handlers() - self._io_loop = IOLoop() - self._reactor = TornadoReactor(self._io_loop) + self._io_loop = IOLoop(make_current=True) + self._reactor = TornadoReactor() + IOLoop.clear_current() def tearDown(self): self._io_loop.close(all_fds=True) @@ -361,7 +362,7 @@ class CompatibilityTests(unittest.TestCase): self.saved_signals = save_signal_handlers() self.io_loop = IOLoop() self.io_loop.make_current() - self.reactor = TornadoReactor(self.io_loop) + self.reactor = TornadoReactor() def tearDown(self): self.reactor.disconnectAll() @@ -385,7 +386,7 @@ class CompatibilityTests(unittest.TestCase): self.write("Hello from tornado!") app = Application([('/', HelloHandler)], log_function=lambda x: None) - server = HTTPServer(app, io_loop=self.io_loop) + server = HTTPServer(app) sock, self.tornado_port = bind_unused_port() server.add_sockets([sock]) @@ -401,7 +402,7 @@ class CompatibilityTests(unittest.TestCase): def tornado_fetch(self, url, runner): responses = [] - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() def callback(response): responses.append(response) @@ -701,7 +702,7 @@ if have_twisted: # get the next-best IOLoop implementation, so use the lowest common # denominator. self.real_io_loop = SelectIOLoop(make_current=False) # type: ignore - reactor = TornadoReactor(io_loop=self.real_io_loop) + reactor = self.real_io_loop.run_sync(gen.coroutine(TornadoReactor)) super(LayeredTwistedIOLoop, self).initialize(reactor=reactor, **kwargs) self.add_callback(self.make_current) diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index de26c42ec..ffccc02d3 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -379,7 +379,7 @@ class ConnectionCloseTest(WebTestCase): def test_connection_close(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) s.connect(("127.0.0.1", self.get_http_port())) - self.stream = IOStream(s, io_loop=self.io_loop) + self.stream = IOStream(s) self.stream.write(b"GET / HTTP/1.0\r\n\r\n") self.wait() @@ -1481,7 +1481,7 @@ class StatusReasonTest(SimpleHandlerTestCase): def get_http_client(self): # simple_httpclient only: curl doesn't expose the reason string - return SimpleAsyncHTTPClient(io_loop=self.io_loop) + return SimpleAsyncHTTPClient() def test_status(self): response = self.fetch("/?code=304") @@ -1520,7 +1520,7 @@ class RaiseWithReasonTest(SimpleHandlerTestCase): def get_http_client(self): # simple_httpclient only: curl doesn't expose the reason string - return SimpleAsyncHTTPClient(io_loop=self.io_loop) + return SimpleAsyncHTTPClient() def test_raise_with_reason(self): response = self.fetch("/") @@ -2115,7 +2115,7 @@ class StreamingRequestBodyTest(WebTestCase): # Use a raw connection so we can control the sending of data. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) s.connect(("127.0.0.1", self.get_http_port())) - stream = IOStream(s, io_loop=self.io_loop) + stream = IOStream(s) stream.write(b"GET " + url + b" HTTP/1.1\r\n") if connection_close: stream.write(b"Connection: close\r\n") @@ -2211,7 +2211,7 @@ class BaseStreamingRequestFlowControlTest(object): def get_http_client(self): # simple_httpclient only: curl doesn't support body_producer. - return SimpleAsyncHTTPClient(io_loop=self.io_loop) + return SimpleAsyncHTTPClient() # Test all the slightly different code paths for fixed, chunked, etc bodies. def test_flow_control_fixed_body(self): diff --git a/tornado/test/websocket_test.py b/tornado/test/websocket_test.py index e0b5573de..5a2a6577c 100644 --- a/tornado/test/websocket_test.py +++ b/tornado/test/websocket_test.py @@ -211,7 +211,7 @@ class WebSocketTest(WebSocketBaseTestCase): def test_websocket_callbacks(self): websocket_connect( 'ws://127.0.0.1:%d/echo' % self.get_http_port(), - io_loop=self.io_loop, callback=self.stop) + callback=self.stop) ws = self.wait().result() ws.write_message('hello') ws.read_message(self.stop) @@ -273,7 +273,6 @@ class WebSocketTest(WebSocketBaseTestCase): with ExpectLog(gen_log, ".*"): yield websocket_connect( 'ws://127.0.0.1:%d/' % port, - io_loop=self.io_loop, connect_timeout=3600) @gen_test @@ -372,8 +371,7 @@ class WebSocketTest(WebSocketBaseTestCase): url = 'ws://127.0.0.1:%d/echo' % port headers = {'Origin': 'http://127.0.0.1:%d' % port} - ws = yield websocket_connect(HTTPRequest(url, headers=headers), - io_loop=self.io_loop) + ws = yield websocket_connect(HTTPRequest(url, headers=headers)) ws.write_message('hello') response = yield ws.read_message() self.assertEqual(response, 'hello') @@ -386,8 +384,7 @@ class WebSocketTest(WebSocketBaseTestCase): url = 'ws://127.0.0.1:%d/echo' % port headers = {'Origin': 'http://127.0.0.1:%d/something' % port} - ws = yield websocket_connect(HTTPRequest(url, headers=headers), - io_loop=self.io_loop) + ws = yield websocket_connect(HTTPRequest(url, headers=headers)) ws.write_message('hello') response = yield ws.read_message() self.assertEqual(response, 'hello') @@ -401,8 +398,7 @@ class WebSocketTest(WebSocketBaseTestCase): headers = {'Origin': '127.0.0.1:%d' % port} with self.assertRaises(HTTPError) as cm: - yield websocket_connect(HTTPRequest(url, headers=headers), - io_loop=self.io_loop) + yield websocket_connect(HTTPRequest(url, headers=headers)) self.assertEqual(cm.exception.code, 403) @gen_test @@ -415,8 +411,7 @@ class WebSocketTest(WebSocketBaseTestCase): headers = {'Origin': 'http://somewhereelse.com'} with self.assertRaises(HTTPError) as cm: - yield websocket_connect(HTTPRequest(url, headers=headers), - io_loop=self.io_loop) + yield websocket_connect(HTTPRequest(url, headers=headers)) self.assertEqual(cm.exception.code, 403) @@ -430,8 +425,7 @@ class WebSocketTest(WebSocketBaseTestCase): headers = {'Origin': 'http://subtenant.localhost'} with self.assertRaises(HTTPError) as cm: - yield websocket_connect(HTTPRequest(url, headers=headers), - io_loop=self.io_loop) + yield websocket_connect(HTTPRequest(url, headers=headers)) self.assertEqual(cm.exception.code, 403) diff --git a/tornado/testing.py b/tornado/testing.py index 46c2d5e19..9979617dc 100644 --- a/tornado/testing.py +++ b/tornado/testing.py @@ -148,8 +148,7 @@ class AsyncTestCase(unittest.TestCase): callbacks should call ``self.stop()`` to signal completion. By default, a new `.IOLoop` is constructed for each test and is available - as ``self.io_loop``. This `.IOLoop` should be used in the construction of - HTTP clients/servers, etc. If the code being tested requires a + as ``self.io_loop``. If the code being tested requires a global `.IOLoop`, subclasses should override `get_new_ioloop` to return it. The `.IOLoop`'s ``start`` and ``stop`` methods should not be @@ -164,7 +163,7 @@ class AsyncTestCase(unittest.TestCase): class MyTestCase(AsyncTestCase): @tornado.testing.gen_test def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() response = yield client.fetch("http://www.tornadoweb.org") # Test contents of response self.assertIn("FriendFeed", response.body) @@ -172,7 +171,7 @@ class AsyncTestCase(unittest.TestCase): # This test uses argument passing between self.stop and self.wait. class MyTestCase2(AsyncTestCase): def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() client.fetch("http://www.tornadoweb.org/", self.stop) response = self.wait() # Test contents of response @@ -181,7 +180,7 @@ class AsyncTestCase(unittest.TestCase): # This test uses an explicit callback-based style. class MyTestCase3(AsyncTestCase): def test_http_fetch(self): - client = AsyncHTTPClient(self.io_loop) + client = AsyncHTTPClient() client.fetch("http://www.tornadoweb.org/", self.handle_fetch) self.wait() @@ -364,11 +363,10 @@ class AsyncHTTPTestCase(AsyncTestCase): self.http_server.add_sockets([sock]) def get_http_client(self): - return AsyncHTTPClient(io_loop=self.io_loop) + return AsyncHTTPClient() def get_http_server(self): - return HTTPServer(self._app, io_loop=self.io_loop, - **self.get_httpserver_options()) + return HTTPServer(self._app, **self.get_httpserver_options()) def get_app(self): """Should be overridden by subclasses to return a @@ -430,7 +428,7 @@ class AsyncHTTPSTestCase(AsyncHTTPTestCase): Interface is generally the same as `AsyncHTTPTestCase`. """ def get_http_client(self): - return AsyncHTTPClient(io_loop=self.io_loop, force_instance=True, + return AsyncHTTPClient(force_instance=True, defaults=dict(validate_cert=False)) def get_httpserver_options(self): diff --git a/tornado/websocket.py b/tornado/websocket.py index 7600910c0..d5a7fa89f 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -1040,7 +1040,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): This class should not be instantiated directly; use the `websocket_connect` function instead. """ - def __init__(self, io_loop, request, on_message_callback=None, + def __init__(self, request, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, max_message_size=None): self.compression_options = compression_options @@ -1073,9 +1073,9 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): request.headers['Sec-WebSocket-Extensions'] = ( 'permessage-deflate; client_max_window_bits') - self.tcp_client = TCPClient(io_loop=io_loop) + self.tcp_client = TCPClient() super(WebSocketClientConnection, self).__init__( - io_loop, None, request, lambda: None, self._on_http_response, + None, request, lambda: None, self._on_http_response, 104857600, self.tcp_client, 65536, 104857600) def close(self, code=None, reason=None): @@ -1179,7 +1179,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): compression_options=self.compression_options) -def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, +def websocket_connect(url, callback=None, connect_timeout=None, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, max_message_size=None): @@ -1210,14 +1210,14 @@ def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, .. versionchanged:: 4.1 Added ``compression_options`` and ``on_message_callback``. - The ``io_loop`` argument is deprecated. .. versionchanged:: 4.5 Added the ``ping_interval``, ``ping_timeout``, and ``max_message_size`` arguments, which have the same meaning as in `WebSocketHandler`. + + .. versionchanged:: 5.0 + The ``io_loop`` argument (deprecated since version 4.1) has been removed. """ - if io_loop is None: - io_loop = IOLoop.current() if isinstance(url, httpclient.HTTPRequest): assert connect_timeout is None request = url @@ -1228,12 +1228,12 @@ def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout) request = httpclient._RequestProxy( request, httpclient.HTTPRequest._DEFAULTS) - conn = WebSocketClientConnection(io_loop, request, + conn = WebSocketClientConnection(request, on_message_callback=on_message_callback, compression_options=compression_options, ping_interval=ping_interval, ping_timeout=ping_timeout, max_message_size=max_message_size) if callback is not None: - io_loop.add_future(conn.connect_future, callback) + IOLoop.current().add_future(conn.connect_future, callback) return conn.connect_future