# flake8: noqa
from __future__ import absolute_import, division, print_function
+
+import subprocess
+import sys
+
from tornado.test.util import unittest
+_import_everything = b"""
+# The event loop is not fork-safe, and it's easy to initialize an asyncio.Future
+# at startup, which in turn creates the default event loop and prevents forking.
+# Explicitly disallow the default event loop so that an error will be raised
+# if something tries to touch it.
+try:
+ import asyncio
+except ImportError:
+ pass
+else:
+ asyncio.set_event_loop(None)
+
+import tornado.auth
+import tornado.autoreload
+import tornado.concurrent
+import tornado.escape
+import tornado.gen
+import tornado.http1connection
+import tornado.httpclient
+import tornado.httpserver
+import tornado.httputil
+import tornado.ioloop
+import tornado.iostream
+import tornado.locale
+import tornado.log
+import tornado.netutil
+import tornado.options
+import tornado.process
+import tornado.simple_httpclient
+import tornado.stack_context
+import tornado.tcpserver
+import tornado.tcpclient
+import tornado.template
+import tornado.testing
+import tornado.util
+import tornado.web
+import tornado.websocket
+import tornado.wsgi
+
+try:
+ import pycurl
+except ImportError:
+ pass
+else:
+ import tornado.curl_httpclient
+"""
+
class ImportTest(unittest.TestCase):
def test_import_everything(self):
- # Some of our modules are not otherwise tested. Import them
- # all (unless they have external dependencies) here to at
- # least ensure that there are no syntax errors.
- import tornado.auth
- import tornado.autoreload
- import tornado.concurrent
- import tornado.escape
- import tornado.gen
- import tornado.http1connection
- import tornado.httpclient
- import tornado.httpserver
- import tornado.httputil
- import tornado.ioloop
- import tornado.iostream
- import tornado.locale
- import tornado.log
- import tornado.netutil
- import tornado.options
- import tornado.process
- import tornado.simple_httpclient
- import tornado.stack_context
- import tornado.tcpserver
- import tornado.tcpclient
- import tornado.template
- import tornado.testing
- import tornado.util
- import tornado.web
- import tornado.websocket
- import tornado.wsgi
-
- # for modules with dependencies, if those dependencies can be loaded,
- # load them too.
-
- def test_import_pycurl(self):
- try:
- import pycurl # type: ignore
- except ImportError:
- pass
- else:
- import tornado.curl_httpclient
+ # Test that all Tornado modules can be imported without side effects,
+ # specifically without initializing the default asyncio event loop.
+ # Since we can't tell which modules may have already beein imported
+ # in our process, do it in a subprocess for a clean slate.
+ proc = subprocess.Popen([sys.executable], stdin=subprocess.PIPE)
+ proc.communicate(_import_everything)
+ self.assertEqual(proc.returncode, 0)
def test_import_aliases(self):
# Ensure we don't delete formerly-documented aliases accidentally.
# WSGI has no facilities for flow control, so just return an already-done
# Future when the interface requires it.
-_dummy_future = Future()
-_dummy_future.set_result(None)
+def _dummy_future():
+ f = Future()
+ f.set_result(None)
+ return f
class _WSGIConnection(httputil.HTTPConnection):
self.write(chunk, callback)
elif callback is not None:
callback()
- return _dummy_future
+ return _dummy_future()
def write(self, chunk, callback=None):
if self._expected_content_remaining is not None:
self._write_buffer.append(chunk)
if callback is not None:
callback()
- return _dummy_future
+ return _dummy_future()
def finish(self):
if (self._expected_content_remaining is not None and