IOLoop poller implementations are now subclasses of IOLoop.
Update testing command-line flags to allow configuration of a non-default IOLoop.
This commit is contained in:
parent
91c5eb83f9
commit
469e227402
|
@ -103,7 +103,20 @@ class IOLoop(Configurable):
|
|||
|
||||
@classmethod
|
||||
def configurable_default(cls):
|
||||
return IOLoop
|
||||
if hasattr(select, "epoll"):
|
||||
# Python 2.6+ on Linux
|
||||
return EPollIOLoop
|
||||
elif hasattr(select, "kqueue"):
|
||||
# Python 2.6+ on BSD or Mac
|
||||
return KQueueIOLoop
|
||||
else:
|
||||
try:
|
||||
# Python 2.5 on Linux with our C module installed
|
||||
from tornado import epoll
|
||||
return EPoll25IOLoop
|
||||
except Exception:
|
||||
# Everything else
|
||||
return SelectIOLoop
|
||||
|
||||
# Constants from the epoll module
|
||||
_EPOLLIN = 0x001
|
||||
|
@ -126,8 +139,8 @@ class IOLoop(Configurable):
|
|||
|
||||
_current = threading.local()
|
||||
|
||||
def initialize(self, impl=None):
|
||||
self._impl = impl or _poll()
|
||||
def initialize(self, impl):
|
||||
self._impl = impl
|
||||
if hasattr(self._impl, 'fileno'):
|
||||
set_close_exec(self._impl.fileno())
|
||||
self._handlers = {}
|
||||
|
@ -643,6 +656,8 @@ class _EPoll(object):
|
|||
_EPOLL_CTL_MOD = 3
|
||||
|
||||
def __init__(self):
|
||||
from tornado import epoll
|
||||
self.epoll = epoll
|
||||
self._epoll_fd = epoll.epoll_create()
|
||||
|
||||
def fileno(self):
|
||||
|
@ -652,16 +667,21 @@ class _EPoll(object):
|
|||
os.close(self._epoll_fd)
|
||||
|
||||
def register(self, fd, events):
|
||||
epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_ADD, fd, events)
|
||||
self.epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_ADD, fd, events)
|
||||
|
||||
def modify(self, fd, events):
|
||||
epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_MOD, fd, events)
|
||||
self.epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_MOD, fd, events)
|
||||
|
||||
def unregister(self, fd):
|
||||
epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_DEL, fd, 0)
|
||||
self.epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_DEL, fd, 0)
|
||||
|
||||
def poll(self, timeout):
|
||||
return epoll.epoll_wait(self._epoll_fd, int(timeout * 1000))
|
||||
return self.epoll.epoll_wait(self._epoll_fd, int(timeout * 1000))
|
||||
|
||||
|
||||
class EPoll25IOLoop(IOLoop):
|
||||
def initialize(self, **kwargs):
|
||||
super(EPoll25IOLoop, self).initialize(impl=_EPoll(), **kwargs)
|
||||
|
||||
|
||||
class _KQueue(object):
|
||||
|
@ -728,6 +748,11 @@ class _KQueue(object):
|
|||
return events.items()
|
||||
|
||||
|
||||
class KQueueIOLoop(IOLoop):
|
||||
def initialize(self, **kwargs):
|
||||
super(KQueueIOLoop, self).initialize(impl=_KQueue(), **kwargs)
|
||||
|
||||
|
||||
class _Select(object):
|
||||
"""A simple, select()-based IOLoop implementation for non-Linux systems"""
|
||||
def __init__(self):
|
||||
|
@ -774,23 +799,11 @@ class _Select(object):
|
|||
events[fd] = events.get(fd, 0) | IOLoop.ERROR
|
||||
return events.items()
|
||||
|
||||
class SelectIOLoop(IOLoop):
|
||||
def initialize(self, **kwargs):
|
||||
super(SelectIOLoop, self).initialize(impl=_Select(), **kwargs)
|
||||
|
||||
# Choose a poll implementation. Use epoll if it is available, fall back to
|
||||
# select() for non-Linux platforms
|
||||
if hasattr(select, "epoll"):
|
||||
# Python 2.6+ on Linux
|
||||
_poll = select.epoll
|
||||
elif hasattr(select, "kqueue"):
|
||||
# Python 2.6+ on BSD or Mac
|
||||
_poll = _KQueue
|
||||
else:
|
||||
try:
|
||||
# Linux systems with our C module installed
|
||||
from tornado import epoll
|
||||
_poll = _EPoll
|
||||
except Exception:
|
||||
# All other systems
|
||||
import sys
|
||||
if "linux" in sys.platform:
|
||||
gen_log.warning("epoll module not found; using select()")
|
||||
_poll = _Select
|
||||
|
||||
class EPollIOLoop(IOLoop):
|
||||
def initialize(self, **kwargs):
|
||||
super(EPollIOLoop, self).initialize(impl=select.epoll(), **kwargs)
|
||||
|
|
|
@ -4,6 +4,9 @@ from __future__ import absolute_import, division, with_statement
|
|||
import logging
|
||||
import textwrap
|
||||
import sys
|
||||
from tornado.httpclient import AsyncHTTPClient
|
||||
from tornado.ioloop import IOLoop
|
||||
from tornado.options import define
|
||||
from tornado.test.util import unittest
|
||||
|
||||
TEST_MODULES = [
|
||||
|
@ -76,6 +79,11 @@ if __name__ == '__main__':
|
|||
|
||||
logging.getLogger("tornado.access").setLevel(logging.CRITICAL)
|
||||
|
||||
define('httpclient', type=str, default=None,
|
||||
callback=AsyncHTTPClient.configure)
|
||||
define('ioloop', type=str, default=None,
|
||||
callback=IOLoop.configure)
|
||||
|
||||
import tornado.testing
|
||||
kwargs = {}
|
||||
if sys.version_info >= (3, 2):
|
||||
|
|
|
@ -471,9 +471,6 @@ def main(**kwargs):
|
|||
"""
|
||||
from tornado.options import define, options, parse_command_line
|
||||
|
||||
define('autoreload', type=bool, default=False,
|
||||
help="DEPRECATED: use tornado.autoreload.main instead")
|
||||
define('httpclient', type=str, default=None)
|
||||
define('exception_on_interrupt', type=bool, default=True,
|
||||
help=("If true (default), ctrl-c raises a KeyboardInterrupt "
|
||||
"exception. This prints a stack trace but cannot interrupt "
|
||||
|
@ -489,10 +486,6 @@ def main(**kwargs):
|
|||
|
||||
argv = [sys.argv[0]] + parse_command_line(sys.argv)
|
||||
|
||||
if options.httpclient:
|
||||
from tornado.httpclient import AsyncHTTPClient
|
||||
AsyncHTTPClient.configure(options.httpclient)
|
||||
|
||||
if not options.exception_on_interrupt:
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
|
@ -526,11 +519,7 @@ def main(**kwargs):
|
|||
gen_log.info('PASS')
|
||||
else:
|
||||
gen_log.error('FAIL')
|
||||
if not options.autoreload:
|
||||
raise
|
||||
if options.autoreload:
|
||||
import tornado.autoreload
|
||||
tornado.autoreload.wait()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
11
tox.ini
11
tox.ini
|
@ -74,6 +74,17 @@ deps =
|
|||
twisted>=11.1.0
|
||||
commands = python -m tornado.test.runtests --httpclient=tornado.curl_httpclient.CurlAsyncHTTPClient {posargs:}
|
||||
|
||||
[testenv:py27-select]
|
||||
# Same as py27-full, but runs the tests with the select IOLoop.
|
||||
# The other tests will run with the most platform-appropriate implementation,
|
||||
# but this one is the lowest common denominator and should work anywhere.
|
||||
basepython = python2.7
|
||||
deps =
|
||||
futures
|
||||
pycurl
|
||||
twisted>=12.0.0
|
||||
commands = python -m tornado.test.runtests --ioloop=tornado.ioloop.SelectIOLoop {posargs:}
|
||||
|
||||
[testenv:pypy-full]
|
||||
# This configuration works with pypy 1.9. pycurl installs ok but
|
||||
# curl_httpclient doesn't work. Twisted works most of the time, but
|
||||
|
|
|
@ -104,3 +104,18 @@ In progress
|
|||
argument.
|
||||
* Keyword arguments to `AsyncHTTPClient.configure` are no longer used
|
||||
when instantiating an implementation subclass directly.
|
||||
* The `IOLoop` poller implementations (``select``, ``epoll``, ``kqueue``)
|
||||
are now available as distinct subclasses of `IOLoop`. Instantiating
|
||||
`IOLoop` will continue to automatically choose the best available
|
||||
implementation.
|
||||
* `IOLoop` now has a static ``configure`` method like the one on
|
||||
`AsyncHTTPClient`, which can be used to select an IOLoop implementation
|
||||
other than the default.
|
||||
* The deprecated ``--autoreload`` option of `tornado.testing.main` has
|
||||
been removed. Use ``python -m tornado.autoreload`` as a prefix command
|
||||
instead.
|
||||
* The ``--httpclient`` option of `tornado.testing.main` has been moved
|
||||
to `tornado.test.runtests` so as not to pollute the application
|
||||
option namespace. The `tornado.options` module's new callback
|
||||
support now makes it easy to add options from a wrapper script
|
||||
instead of putting all possible options in `tornado.testing.main`.
|
||||
|
|
Loading…
Reference in New Issue