diff --git a/setup.py b/setup.py index dcbb1bc8..4434abca 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,7 @@ from distutils.core import Extension # no compiler is available. from distutils.command.build_ext import build_ext + class custom_build_ext(build_ext): """Allow C extension building to fail. @@ -104,7 +105,7 @@ with open('README.rst') as f: kwargs['long_description'] = f.read() if (platform.python_implementation() == 'CPython' and - os.environ.get('TORNADO_EXTENSION') != '0'): + os.environ.get('TORNADO_EXTENSION') != '0'): # This extension builds and works on pypy as well, although pypy's jit # produces equivalent performance. kwargs['ext_modules'] = [ @@ -120,16 +121,21 @@ if (platform.python_implementation() == 'CPython' and if setuptools is not None: # If setuptools is not available, you're on your own for dependencies. - install_requires = ['certifi'] + install_requires = [] if sys.version_info < (3, 2): install_requires.append('backports.ssl_match_hostname') + if sys.version_info < (3, 4): + # 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') kwargs['install_requires'] = install_requires setup( name="tornado", version=version, - packages = ["tornado", "tornado.test", "tornado.platform"], - package_data = { + packages=["tornado", "tornado.test", "tornado.platform"], + package_data={ # data files need to be listed both here (which determines what gets # installed) and in MANIFEST.in (which determines what gets included # in the sdist tarball) diff --git a/tornado/netutil.py b/tornado/netutil.py index 48355f94..3464255f 100644 --- a/tornado/netutil.py +++ b/tornado/netutil.py @@ -18,7 +18,6 @@ from __future__ import absolute_import, division, print_function, with_statement -import certifi import errno import os import sys @@ -36,6 +35,14 @@ except ImportError: # ssl is not available on Google App Engine ssl = None +try: + import certifi +except ImportError: + # certifi is optional as long as we have ssl.create_default_context. + if not hasattr(ssl, 'create_default_context'): + raise + certifi = None + try: xrange # py2 except NameError: diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index bb080af9..ffa03ea6 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -234,7 +234,10 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): ssl_options["cert_reqs"] = ssl.CERT_REQUIRED if self.request.ca_certs is not None: ssl_options["ca_certs"] = self.request.ca_certs - else: + elif not hasattr(ssl, 'create_default_context'): + # When create_default_context is present, + # we can omit the "ca_certs" parameter entirely, + # which avoids the dependency on "certifi" for py34. ssl_options["ca_certs"] = _default_ca_certs() if self.request.client_key is not None: ssl_options["keyfile"] = self.request.client_key diff --git a/tornado/test/iostream_test.py b/tornado/test/iostream_test.py index 227e9ad5..c1662885 100644 --- a/tornado/test/iostream_test.py +++ b/tornado/test/iostream_test.py @@ -10,7 +10,6 @@ from tornado.stack_context import NullContext from tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, bind_unused_port, ExpectLog, gen_test from tornado.test.util import unittest, skipIfNonUnix, refusing_port from tornado.web import RequestHandler, Application -import certifi import errno import logging import os diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index be3c2d94..2d72992e 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -192,9 +192,6 @@ class SimpleHTTPClientTestMixin(object): response = self.wait() response.rethrow() - def test_default_certificates_exist(self): - open(_default_ca_certs()).close() - def test_gzip(self): # All the tests in this file should be using gzip, but this test # ensures that it is in fact getting compressed.