From: Ben Darnell Date: Sun, 18 Oct 2015 20:34:47 +0000 (+0200) Subject: Make singledispatch and backports_abc mandatory dependencies. X-Git-Tag: v4.3.0b1~2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b3e31be1f55aba7d87d75eb568769e7f107a736;p=thirdparty%2Ftornado.git Make singledispatch and backports_abc mandatory dependencies. I anticipate confusion around the differing behavior based on whether or not these packages are installed, so it's better to just make them mandatory (except on app engine). --- diff --git a/.travis.yml b/.travis.yml index f7affbba5..2e34e3915 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,11 @@ install: # always install unittest2 on py26 even if $DEPS is unset - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then travis_retry pip install unittest2; fi - if [[ $TRAVIS_PYTHON_VERSION == 2* && $DEPS == true ]]; then travis_retry pip install futures mock Monotime trollius; fi - - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then travis_retry pip install singledispatch; fi - - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' && $DEPS == true ]]; then travis_retry pip install futures mock singledispatch; fi + - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' && $DEPS == true ]]; then travis_retry pip install futures mock; fi # TODO(bdarnell): pycares tests are currently disabled on travis due to ipv6 issues. #- if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* && $DEPS == true ]]; then travis_retry pip install pycares; fi - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* && $DEPS == true ]]; then travis_retry pip install pycurl; fi - - if [[ $TRAVIS_PYTHON_VERSION == '3.2' && $DEPS == true ]]; then travis_retry pip install mock singledispatch; fi + - if [[ $TRAVIS_PYTHON_VERSION == '3.2' && $DEPS == true ]]; then travis_retry pip install mock; fi # Twisted runs on 2.x and 3.3+, but is flaky on pypy. - if [[ $TRAVIS_PYTHON_VERSION != '3.2' && $TRAVIS_PYTHON_VERSION != 'pypy'* && $DEPS == true ]]; then travis_retry pip install Twisted; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' && $DEPS == true ]]; then travis_retry pip install sphinx sphinx_rtd_theme; fi diff --git a/setup.py b/setup.py index 49e436ec3..c63e14b44 100644 --- a/setup.py +++ b/setup.py @@ -125,10 +125,13 @@ if setuptools is not None: if sys.version_info < (3, 2): install_requires.append('backports.ssl_match_hostname') if sys.version_info < (3, 4): + install_requires.append('singledispatch') # Certifi is also optional on 2.7.9+, although making our dependencies # conditional on micro version numbers seems like a bad idea # until we have more declarative metadata. install_requires.append('certifi') + if sys.version_info < (3, 5): + install_requires.append('backports_abc>=0.4') kwargs['install_requires'] = install_requires setup( diff --git a/tornado/gen.py b/tornado/gen.py index 84a2da683..bf184e548 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -79,6 +79,7 @@ from __future__ import absolute_import, division, print_function, with_statement import collections import functools import itertools +import os import sys import textwrap import types @@ -90,30 +91,38 @@ from tornado import stack_context from tornado.util import raise_exc_info try: - from functools import singledispatch # py34+ -except ImportError as e: try: - from singledispatch import singledispatch # backport + from functools import singledispatch # py34+ except ImportError: - singledispatch = None - + from singledispatch import singledispatch # backport +except ImportError: + # In most cases, singledispatch is required (to avoid + # difficult-to-diagnose problems in which the functionality + # available differs depending on which invisble packages are + # installed). However, in Google App Engine third-party + # dependencies are more trouble so we allow this module to be + # imported without it. + if 'APPENGINE_RUNTIME' not in os.environ: + raise + singledispatch = None try: - from collections.abc import Generator as GeneratorType # py35+ -except ImportError: try: - from backports_abc import Generator as GeneratorType + from collections.abc import Generator as GeneratorType # py35+ except ImportError: - from types import GeneratorType + from backports_abc import Generator as GeneratorType -try: - from inspect import isawaitable # py35+ -except ImportError: try: - from backports_abc import isawaitable + from inspect import isawaitable # py35+ except ImportError: - def isawaitable(x): - return False + from backports_abc import isawaitable +except ImportError: + if 'APPENGINE_RUNTIME' not in os.environ: + raise + from types import GeneratorType + + def isawaitable(x): + return False try: import builtins # py3 diff --git a/tornado/test/asyncio_test.py b/tornado/test/asyncio_test.py index 52ba9d353..b50b2048e 100644 --- a/tornado/test/asyncio_test.py +++ b/tornado/test/asyncio_test.py @@ -25,9 +25,6 @@ else: # This is used in dynamically-evaluated code, so silence pyflakes. to_asyncio_future -skipIfNoSingleDispatch = unittest.skipIf( - gen.singledispatch is None, "singledispatch module not present") - @unittest.skipIf(asyncio is None, "asyncio module not present") class AsyncIOLoopTest(AsyncTestCase): @@ -41,7 +38,6 @@ class AsyncIOLoopTest(AsyncTestCase): asyncio.get_event_loop().call_soon(self.stop) self.wait() - @skipIfNoSingleDispatch @gen_test def test_asyncio_future(self): # Test that we can yield an asyncio future from a tornado coroutine. @@ -51,7 +47,6 @@ class AsyncIOLoopTest(AsyncTestCase): self.assertEqual(x, 42) @skipBefore33 - @skipIfNoSingleDispatch @gen_test def test_asyncio_yield_from(self): # Test that we can use asyncio coroutines with 'yield from' diff --git a/tornado/test/twisted_test.py b/tornado/test/twisted_test.py index 3be087cb1..8389e60bb 100644 --- a/tornado/test/twisted_test.py +++ b/tornado/test/twisted_test.py @@ -72,9 +72,6 @@ from tornado.web import RequestHandler, Application skipIfNoTwisted = unittest.skipUnless(have_twisted, "twisted module not present") -skipIfNoSingleDispatch = unittest.skipIf( - gen.singledispatch is None, "singledispatch module not present") - def save_signal_handlers(): saved = {} @@ -495,7 +492,6 @@ class CompatibilityTests(unittest.TestCase): 'http://127.0.0.1:%d' % self.tornado_port, self.run_reactor) self.assertEqual(response, 'Hello from tornado!') - @skipIfNoSingleDispatch def testTornadoServerTwistedCoroutineClientIOLoop(self): self.start_tornado_server() response = self.twisted_coroutine_fetch( @@ -504,7 +500,6 @@ class CompatibilityTests(unittest.TestCase): @skipIfNoTwisted -@skipIfNoSingleDispatch class ConvertDeferredTest(unittest.TestCase): def test_success(self): @inlineCallbacks