]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
IOLoop poller implementations are now subclasses of IOLoop.
authorBen Darnell <ben@bendarnell.com>
Mon, 1 Oct 2012 05:57:32 +0000 (22:57 -0700)
committerBen Darnell <ben@bendarnell.com>
Mon, 1 Oct 2012 06:07:51 +0000 (23:07 -0700)
Update testing command-line flags to allow configuration of a non-default
IOLoop.

tornado/ioloop.py
tornado/test/runtests.py
tornado/testing.py
tox.ini
website/sphinx/releases/next.rst

index 29e0edb6ced38c80e7a3da28fe52f6cb90acf5e9..f2d84480bad2cb1424919ee736d3e295b1c639c7 100644 (file)
@@ -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)
index 1f8e43ea7e5dc6b8b8f095334771fc9ebc94c2ae..103df58eb302604e1f31715ef74a4a67425a62b7 100644 (file)
@@ -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):
index 34aa1b89b465f5dedaa074406b68177c333ce6cf..b34b6dac970f5ea4593393e50f0c8b95c450cd04 100644 (file)
@@ -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()
+        raise
 
 if __name__ == '__main__':
     main()
diff --git a/tox.ini b/tox.ini
index 203550cbffc4e8b1a926fc98f8f7f7fb6536ba4f..9fb6fc1129ac0749c1671a0b9ec24ca1a7676967 100644 (file)
--- a/tox.ini
+++ b/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
index 4ff63115f576e2fff59324b71b7e46c12697c115..f4e8bbaaf3363acd243e0849ec2be9511315a928 100644 (file)
@@ -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`.