[Python-modules-commits] [python-urllib3] 02/10: Import python-urllib3_1.13.1.orig.tar.gz

Daniele Tricoli eriol-guest at moszumanska.debian.org
Wed Dec 23 23:38:59 UTC 2015


This is an automated email from the git hooks/post-receive script.

eriol-guest pushed a commit to branch master
in repository python-urllib3.

commit 49444bdd74c2a37b97d86fc9cb5b85a28ffd659d
Author: Daniele Tricoli <eriol at mornie.org>
Date:   Wed Dec 23 22:33:11 2015 +0100

    Import python-urllib3_1.13.1.orig.tar.gz
---
 CHANGES.rst                                     | 23 ++++++++
 CONTRIBUTORS.txt                                | 18 +++++-
 Makefile                                        |  3 +-
 PKG-INFO                                        | 25 ++++++++-
 docs/index.rst                                  |  2 +-
 docs/managers.rst                               | 11 ++++
 docs/security.rst                               | 73 +++++++++++++++++++------
 dummyserver/certs/server.ipv6addr.crt           | 16 ++++++
 dummyserver/certs/server.ipv6addr.key           | 27 +++++++++
 dummyserver/handlers.py                         | 11 ++--
 dummyserver/proxy.py                            |  9 +--
 dummyserver/server.py                           |  6 ++
 dummyserver/testcase.py                         | 19 +++++--
 setup.cfg                                       |  9 +++
 setup.py                                        | 11 ++--
 test/test_util.py                               | 30 ++++++++++
 test/with_dummyserver/test_connectionpool.py    | 44 +++++++--------
 test/with_dummyserver/test_https.py             | 32 +++++++++--
 test/with_dummyserver/test_poolmanager.py       | 12 +++-
 test/with_dummyserver/test_proxy_poolmanager.py |  8 +--
 test/with_dummyserver/test_socketlevel.py       | 71 ++++++++++++++++++++++++
 urllib3.egg-info/PKG-INFO                       | 25 ++++++++-
 urllib3.egg-info/SOURCES.txt                    |  2 +
 urllib3.egg-info/pbr.json                       |  2 +-
 urllib3.egg-info/requires.txt                   |  7 +--
 urllib3/__init__.py                             | 32 +++++++++--
 urllib3/_collections.py                         |  7 ++-
 urllib3/connection.py                           | 39 ++++++++-----
 urllib3/connectionpool.py                       | 34 ++++++------
 urllib3/contrib/appengine.py                    | 23 ++++----
 urllib3/contrib/ntlmpool.py                     |  1 +
 urllib3/contrib/pyopenssl.py                    | 35 ++++++------
 urllib3/exceptions.py                           | 14 ++++-
 urllib3/fields.py                               |  1 +
 urllib3/filepost.py                             |  1 +
 urllib3/packages/__init__.py                    |  1 +
 urllib3/poolmanager.py                          |  3 +-
 urllib3/request.py                              |  4 +-
 urllib3/response.py                             | 53 ++++++++++++++----
 urllib3/util/__init__.py                        | 20 +++++++
 urllib3/util/connection.py                      |  1 +
 urllib3/util/request.py                         |  1 +
 urllib3/util/response.py                        |  3 +-
 urllib3/util/retry.py                           |  7 ++-
 urllib3/util/ssl_.py                            | 39 +++++++++++--
 urllib3/util/timeout.py                         |  8 ++-
 urllib3/util/url.py                             |  5 +-
 47 files changed, 650 insertions(+), 178 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index ea10bb7..674aa35 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,29 @@
 Changes
 =======
 
+1.13.1 (2015-12-18)
++++++++++++++++++++
+
+* Fixed regression in IPv6 + SSL for match_hostname. (Issue #761)
+
+
+1.13 (2015-12-14)
++++++++++++++++++
+
+* Fixed ``pip install urllib3[secure]`` on modern pip. (Issue #706)
+
+* pyopenssl: Fixed SSL3_WRITE_PENDING error. (Issue #717)
+
+* pyopenssl: Support for TLSv1.1 and TLSv1.2. (Issue #696)
+
+* Close connections more defensively on exception. (Issue #734)
+
+* Adjusted ``read_chunked`` to handle gzipped, chunk-encoded bodies without
+  repeatedly flushing the decoder, to function better on Jython. (Issue #743)
+
+* Accept ``ca_cert_dir`` for SSL-related PoolManager configuration. (Issue #758)
+
+
 1.12 (2015-09-03)
 +++++++++++++++++
 
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index b8a0f01..448a4ab 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -153,7 +153,7 @@ In chronological order:
 
 * Jon Wayne Parrott <jonwayne at google.com>
   * App Engine environment tests.
-  
+
 * John Krauss <https://github.com/talos>
   * Clues to debugging problems with `cryptography` dependency in docs
 
@@ -169,6 +169,20 @@ In chronological order:
 * Jordan Moldow <https://github.com/jmoldow>
   * Fix low-level exceptions leaking from ``HTTPResponse.stream()``.
 
+* Predrag Gruevski <https://github.com/obi1kenobi>
+  * Made cert digest comparison use a constant-time algorithm.
+
+* Adam Talsma <https://github.com/a-tal>
+  * Bugfix to ca_cert file paths.
+
+* Evan Meagher <https://evanmeagher.net>
+  * Bugfix related to `memoryview` usage in PyOpenSSL adapter
+
+* John Vandenberg <jayvdb at gmail.com>
+  * Python 2.6 fixes; pyflakes and pep8 compliance
+
+* Andy Caldwell <andy.m.caldwell at googlemail.com>
+  * Bugfix related to reusing connections in indeterminate states.
+
 * [Your name or handle] <[email or website]>
   * [Brief summary of your changes]
-
diff --git a/Makefile b/Makefile
index 3b3314e..8236cc8 100644
--- a/Makefile
+++ b/Makefile
@@ -30,8 +30,7 @@ clean:
 	find . -name "*.py[oc]" -delete
 	find . -name "__pycache__" -delete
 	rm -f $(REQUIREMENTS_OUT)
-	rm -rf docs/_build
-	rm -rf build/
+	rm -rf docs/_build build/ dist/
 
 test: requirements
 	nosetests
diff --git a/PKG-INFO b/PKG-INFO
index cdd3ed3..a375cfe 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: urllib3
-Version: 1.12
+Version: 1.13.1
 Summary: HTTP library with thread-safe connection pooling, file post, and more.
 Home-page: http://urllib3.readthedocs.org/
 Author: Andrey Petrov
@@ -156,6 +156,29 @@ Description: =======
         Changes
         =======
         
+        1.13.1 (2015-12-18)
+        +++++++++++++++++++
+        
+        * Fixed regression in IPv6 + SSL for match_hostname. (Issue #761)
+        
+        
+        1.13 (2015-12-14)
+        +++++++++++++++++
+        
+        * Fixed ``pip install urllib3[secure]`` on modern pip. (Issue #706)
+        
+        * pyopenssl: Fixed SSL3_WRITE_PENDING error. (Issue #717)
+        
+        * pyopenssl: Support for TLSv1.1 and TLSv1.2. (Issue #696)
+        
+        * Close connections more defensively on exception. (Issue #734)
+        
+        * Adjusted ``read_chunked`` to handle gzipped, chunk-encoded bodies without
+          repeatedly flushing the decoder, to function better on Jython. (Issue #743)
+        
+        * Accept ``ca_cert_dir`` for SSL-related PoolManager configuration. (Issue #758)
+        
+        
         1.12 (2015-09-03)
         +++++++++++++++++
         
diff --git a/docs/index.rst b/docs/index.rst
index 78d3601..29e7ad7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -288,7 +288,7 @@ You may also stream your response and get data as they come (e.g. when using
 
 ::
 
-    >>> from urllib3 import PoolManager
+    >>> import urllib3
     >>> http = urllib3.PoolManager()
 
     >>> r = http.request("GET", "http://httpbin.org/stream/3")
diff --git a/docs/managers.rst b/docs/managers.rst
index 6c841b7..825e2f4 100644
--- a/docs/managers.rst
+++ b/docs/managers.rst
@@ -70,6 +70,17 @@ connections and individual per-server:port
 :class:`~urllib3.connectionpool.HTTPSConnectionPool` instances for tunnelled
 HTTPS connections.
 
+Example using proxy authentication:
+
+::
+
+	>>> headers = urllib3.make_headers(proxy_basic_auth='myusername:mypassword')
+	>>> proxy = urllib3.ProxyManager('http://localhost:3128', proxy_headers=headers)
+	>>> r = proxy.request('GET', 'http://example.com/')
+	>>> r.status
+	200
+
+
 API
 ---
     .. autoclass:: ProxyManager
diff --git a/docs/security.rst b/docs/security.rst
index 0f5aa1c..48de053 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -185,21 +185,8 @@ Unverified HTTPS requests will trigger a warning via Python's ``warnings`` modul
 This would be a great time to enable HTTPS verification:
 :ref:`certifi-with-urllib3`.
 
-If you know what you're doing and would like to disable this and other warnings,
-you can use :func:`~urllib3.disable_warnings`::
-
-    import urllib3
-    urllib3.disable_warnings()
+For info about disabling warnings, see `Disabling Warnings`_.
 
-Making unverified HTTPS requests is strongly discouraged. ˙ ͜ʟ˙
-
-Alternatively, if you are using Python's ``logging`` module, you can capture the
-warnings to your own log::
-
-	logging.captureWarnings(True)
-
-Capturing the warnings to your own log is much preferred over simply disabling
-the warnings.
 
 InsecurePlatformWarning
 -----------------------
@@ -216,6 +203,58 @@ If you encounter this warning, it is strongly recommended you upgrade to a
 newer Python version, or that you use pyOpenSSL as described in the
 :ref:`pyopenssl` section.
 
-If you know what you are doing and would like to disable this and other
-warnings, please consult the :ref:`insecurerequestwarning` section for
-instructions on how to handle the warnings.
+For info about disabling warnings, see `Disabling Warnings`_.
+
+
+SNIMissingWarning
+-----------------
+
+.. versionadded:: 1.13
+
+Certain Python distributions (specifically, versions of Python earlier than
+2.7.9) and older OpenSSLs have restrictions that prevent them from using the
+SNI (Server Name Indication) extension. This can cause unexpected behaviour
+when making some HTTPS requests, usually causing the server to present the a
+TLS certificate that is not valid for the website you're trying to access.
+
+If you encounter this warning, it is strongly recommended that you upgrade
+to a newer Python version, or that you use pyOpenSSL as described in the
+:ref:`pyopenssl` section.
+
+For info about disabling warnings, see `Disabling Warnings`_.
+
+
+Disabling Warnings
+------------------
+
+Making unverified HTTPS requests is strongly discouraged. ˙ ͜ʟ˙
+
+But if you understand the ramifications and still want to do it...
+
+Within the code
++++++++++++++++
+
+If you know what you're doing and would like to disable all ``urllib3`` warnings,
+you can use :func:`~urllib3.disable_warnings`::
+
+    import urllib3
+    urllib3.disable_warnings()
+
+Alternatively, if you are using Python's ``logging`` module, you can capture the
+warnings to your own log::
+
+	logging.captureWarnings(True)
+
+Capturing the warnings to your own log is much preferred over simply disabling
+the warnings.
+
+Without modifying code
+++++++++++++++++++++++
+
+If you are using a program that uses ``urllib3`` and don't want to change the
+code, you can suppress warnings by setting the ``PYTHONWARNINGS`` environment
+variable in Python 2.7+ or by using the ``-W`` flag with the Python
+interpreter (see `docs
+<https://docs.python.org/2/using/cmdline.html#cmdoption-W>`_), such as::
+
+    PYTHONWARNINGS="ignore:Unverified HTTPS request" ./do-insecure-request.py
diff --git a/dummyserver/certs/server.ipv6addr.crt b/dummyserver/certs/server.ipv6addr.crt
new file mode 100644
index 0000000..c32a0ce
--- /dev/null
+++ b/dummyserver/certs/server.ipv6addr.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAX2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDDAM6OjEw
+HhcNMTUxMjE1MTY0NjQxWhcNMjEwODAyMDAwMDAwWjAOMQwwCgYDVQQDDAM6OjEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvFke8g6Pco24cdWuOD8Wb
+blIUH6iieNpJqcdNTzKUgtWvlpDeiIOweTuawUWX7bz35fn2KBMty68tmz+64iWJ
+AKe6tJtbXQHty+Y09CPDkkC8f0cmXjqwnNbMT7kVPTaPQZkW7hnGS4XgpnzswpqP
+dMLpUzYwoucaScC/flawLafP3jq6hfae2F5wafwPIVvlURL7ZR7FZPuLW2L4T1Wu
+BHc6gOPQfohjQtiiTNtcEIhsmA3zY4DWuMUJePrEtXhPqcXtogoEiwzLKBeKOYJu
+LIQ3++nWLel+HPvhg52wT4Dhb45PQy55ziyelXiHSro5PQmXTiQebuPMLy/8CiSn
+AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAILPtFVSOrXiXQ3b8Gslh4TOxxTPSdnO
+AkOooYyg5oLJy+CAnDL+u+mFCDFC2maDPm3qyeAn31h5aDyazCzyDvVFVw2uWSuG
+a67YNbCLrVBLVIgqyJfMayY3rcjz6rV4n7hpHn42zuwaI8H1z2T1bjvNU6nsizNK
+qo80nvJ6Kge2kbAa0aMOIHsGX4KGiUwUb4+LpRAP5ZDC8EnDNNfURt1w94nnAH70
+V1RgztaAlVNcPqrSMBLXryNXz+X+Hyd79Nd5runemYUG4fQ50jabC5WHeXqH0uOC
+sDtBgqWHxcxnAQhhJ8jF7wodcUjv5AE204ECmZgyQ475kuZpSh6+IvQ=
+-----END CERTIFICATE-----
diff --git a/dummyserver/certs/server.ipv6addr.key b/dummyserver/certs/server.ipv6addr.key
new file mode 100644
index 0000000..0891327
--- /dev/null
+++ b/dummyserver/certs/server.ipv6addr.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEArxZHvIOj3KNuHHVrjg/Fm25SFB+oonjaSanHTU8ylILVr5aQ
+3oiDsHk7msFFl+289+X59igTLcuvLZs/uuIliQCnurSbW10B7cvmNPQjw5JAvH9H
+Jl46sJzWzE+5FT02j0GZFu4ZxkuF4KZ87MKaj3TC6VM2MKLnGknAv35WsC2nz946
+uoX2nthecGn8DyFb5VES+2UexWT7i1ti+E9VrgR3OoDj0H6IY0LYokzbXBCIbJgN
+82OA1rjFCXj6xLV4T6nF7aIKBIsMyygXijmCbiyEN/vp1i3pfhz74YOdsE+A4W+O
+T0Muec4snpV4h0q6OT0Jl04kHm7jzC8v/AokpwIDAQABAoIBAB5Av0x3gozRQGly
+cI8vcnmU6mHHxp+sOiuYRnO5R4gZw0p/vbB17itEB2SKGLhTv98lwbci3Y2AMFi1
+BqIICWxOzKyaIG38+CRaowBrXvKgBseLRoP+rC1wLD1JWTWuSgsezpEDuzhkPFHA
+8r0GMyauii8+zZJB06TbMY7lCZ2PPKFGtojhbRTe//Nnk925KzSQz7Rk/ylouHra
+4Zi9lDodGvZMhZ8zoNDL2/yvCiDIWffpsdFKn4iKNeme1L7JE8AHBeCFo4eIKeAU
+uPlZDFgo/WdDVQQO7LnBv7tRVUB89ARBc9Egt0JoUpSq9pDaMkiBjcJcNiHkbvNj
+csFN5GECgYEA44VVoxouGs08TqnJmlJvVu4hA5+te50POQbAlcOR+rLpwl0bPuti
+tTaarO4hYwtB87s1owdOOIIqfFSoUTZKy8Ip2OE7pU5CYNZU6b/Z3bWn/+p0mOhF
+aoB/FuifPcepY5Fspx2SFFOlHxrkIEkkk1FBWEX9uDPzvJoLsg6jAMUCgYEAxQDC
+eFj/Mgjb4oIAtBZJGkRpkNK0Ngw2+Mi2ApEVrlylN4vAtNEBa3HRkZprhPrBIqhw
+k129jJ81nBWOPDFqhrqmlfolA2K8YxD6wyE6h6qPyO55BbUfAY1uS8ObNLvWZC4o
+hO5+AHzMnRc8Qi7CVvPVNbSPE5x5gaCWMiHWDnsCgYEAyfdSTbavtpr5LdsKWzNS
+IpjANbdJCLIjETwtOMSikSjA2QhNZ00MElCmfVvlx0X3BaTpuA6EISVrEXMU9wJ6
+4uU4wI0vpU4THmMkfVsQyv62YzZ8yj9lX2Uxa+STdwQGGZy+FprpUaHuse3tE7vZ
+++vlVbbLwvhbJNCaETVs/QECgYApYV139gm0stOtIm2PZlb4o4IhH4EnES3C2DYT
+F/Kb623w2vQhhv1rWj8Q/IS1LA7BfuwWqEwWa6LRJF36Gs8rea1gN2jq6yRzEq/5
+qNMoiBUnuZ/GKSNYKiMO2wmQ7Bu+c0ujkIz7ATvhi23m4PeFWDZiz4h2MBn9toOW
+CDF0XQKBgQCurY35+4jdMOtMuAHquAEtzpf5zbO8p9Bj5qet8N+QXuGTXwaGXlkT
+S6i2iXjboNIWfPhqna+BMAmw+NP4TYiNgWoiRd27SDY8LcPXJee8c0+iWKsJkdl8
+90guxzVXSZg478by9ob83Zod2xBhzUSXYGuQrOrItiuiSnMMhHgtrw==
+-----END RSA PRIVATE KEY-----
diff --git a/dummyserver/handlers.py b/dummyserver/handlers.py
index 43398cd..fb6f44f 100644
--- a/dummyserver/handlers.py
+++ b/dummyserver/handlers.py
@@ -28,8 +28,8 @@ class Response(object):
     def __call__(self, request_handler):
         status, reason = self.status.split(' ', 1)
         request_handler.set_status(int(status), reason)
-        for header,value in self.headers:
-            request_handler.add_header(header,value)
+        for header, value in self.headers:
+            request_handler.add_header(header, value)
 
         # chunked
         if isinstance(self.body, list):
@@ -48,6 +48,7 @@ class Response(object):
 
 RETRY_TEST_NAMES = collections.defaultdict(int)
 
+
 class TestingApp(RequestHandler):
     """
     Simple app that performs various operations, useful for testing an HTTP
@@ -136,8 +137,8 @@ class TestingApp(RequestHandler):
         files_ = request.files.get(param)
 
         if len(files_) != 1:
-            return Response("Expected 1 file for '%s', not %d" %(param, len(files_)),
-                                                    status='400 Bad Request')
+            return Response("Expected 1 file for '%s', not %d" % (param, len(files_)),
+                            status='400 Bad Request')
         file_ = files_[0]
 
         data = file_['body']
@@ -277,7 +278,7 @@ def _parse_header(line):
             value = p[i + 1:].strip()
             params.append((name, value))
     params = email.utils.decode_params(params)
-    params.pop(0) # get rid of the dummy again
+    params.pop(0)  # get rid of the dummy again
     pdict = {}
     for name, value in params:
         value = email.utils.collapse_rfc2231_value(value)
diff --git a/dummyserver/proxy.py b/dummyserver/proxy.py
index aca92a7..5b9984d 100755
--- a/dummyserver/proxy.py
+++ b/dummyserver/proxy.py
@@ -45,14 +45,14 @@ class ProxyHandler(tornado.web.RequestHandler):
 
         def handle_response(response):
             if response.error and not isinstance(response.error,
-                    tornado.httpclient.HTTPError):
+                                                 tornado.httpclient.HTTPError):
                 self.set_status(500)
                 self.write('Internal server error:\n' + str(response.error))
                 self.finish()
             else:
                 self.set_status(response.code)
                 for header in ('Date', 'Cache-Control', 'Server',
-                        'Content-Type', 'Location'):
+                               'Content-Type', 'Location'):
                     v = response.headers.get(header)
                     if v:
                         self.set_header(header, v)
@@ -60,7 +60,8 @@ class ProxyHandler(tornado.web.RequestHandler):
                     self.write(response.body)
                 self.finish()
 
-        req = tornado.httpclient.HTTPRequest(url=self.request.uri,
+        req = tornado.httpclient.HTTPRequest(
+            url=self.request.uri,
             method=self.request.method, body=self.request.body,
             headers=self.request.headers, follow_redirects=False,
             allow_nonstandard_methods=True)
@@ -133,5 +134,5 @@ if __name__ == '__main__':
     if len(sys.argv) > 1:
         port = int(sys.argv[1])
 
-    print ("Starting HTTP proxy on port %d" % port)
+    print("Starting HTTP proxy on port %d" % port)
     run_proxy(port)
diff --git a/dummyserver/server.py b/dummyserver/server.py
index e0b6345..ef053a7 100755
--- a/dummyserver/server.py
+++ b/dummyserver/server.py
@@ -34,10 +34,16 @@ NO_SAN_CERTS = {
     'certfile': os.path.join(CERTS_PATH, 'server.no_san.crt'),
     'keyfile': DEFAULT_CERTS['keyfile']
 }
+IPV6_ADDR_CERTS = {
+    'certfile': os.path.join(CERTS_PATH, 'server.ipv6addr.crt'),
+    'keyfile': os.path.join(CERTS_PATH, 'server.ipv6addr.key'),
+}
 DEFAULT_CA = os.path.join(CERTS_PATH, 'cacert.pem')
 DEFAULT_CA_BAD = os.path.join(CERTS_PATH, 'client_bad.pem')
 NO_SAN_CA = os.path.join(CERTS_PATH, 'cacert.no_san.pem')
 DEFAULT_CA_DIR = os.path.join(CERTS_PATH, 'ca_path_test')
+IPV6_ADDR_CA = os.path.join(CERTS_PATH, 'server.ipv6addr.crt')
+
 
 def _has_ipv6(host):
     """ Returns True if the system can bind an IPv6 address. """
diff --git a/dummyserver/testcase.py b/dummyserver/testcase.py
index e5ae51b..f5588a0 100644
--- a/dummyserver/testcase.py
+++ b/dummyserver/testcase.py
@@ -42,10 +42,10 @@ class SocketDummyServerTestCase(unittest.TestCase):
     @classmethod
     def start_response_handler(cls, response, num=1, block_send=None):
         ready_event = threading.Event()
+
         def socket_handler(listener):
             for _ in range(num):
                 ready_event.set()
-                ready_event.clear()
 
                 sock = listener.accept()[0]
                 consume_socket(sock)
@@ -61,9 +61,9 @@ class SocketDummyServerTestCase(unittest.TestCase):
     @classmethod
     def start_basic_handler(cls, **kw):
         return cls.start_response_handler(
-           b'HTTP/1.1 200 OK\r\n'
-           b'Content-Length: 0\r\n'
-           b'\r\n', **kw)
+            b'HTTP/1.1 200 OK\r\n'
+            b'Content-Length: 0\r\n'
+            b'\r\n', **kw)
 
     @classmethod
     def tearDownClass(cls):
@@ -113,6 +113,17 @@ class HTTPSDummyServerTestCase(HTTPDummyServerTestCase):
     certs = DEFAULT_CERTS
 
 
+class IPV6HTTPSDummyServerTestCase(HTTPSDummyServerTestCase):
+    host = '::1'
+
+    @classmethod
+    def setUpClass(cls):
+        if not socket.has_ipv6:
+            raise SkipTest('IPv6 not available')
+        else:
+            super(IPV6HTTPSDummyServerTestCase, cls).setUpClass()
+
+
 class HTTPDummyProxyTestCase(unittest.TestCase):
 
     http_host = 'localhost'
diff --git a/setup.cfg b/setup.cfg
index 6a64ffa..b5fe992 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,11 +6,20 @@ cover-min-percentage = 100
 cover-erase = true
 
 [flake8]
+exclude = ./docs/conf.py,./test/*,./urllib3/packages/*
 max-line-length = 99
 
 [wheel]
 universal = 1
 
+[metadata]
+provides-extra = secure
+requires-dist = 
+	pyOpenSSL>=0.13; python_version<="2.7" and extra == 'secure'
+	ndg-httpsclient; python_version<="2.7" and extra == 'secure'
+	pyasn1; python_version<="2.7" and extra == 'secure'
+	certifi; extra == 'secure'
+
 [egg_info]
 tag_build = 
 tag_date = 0
diff --git a/setup.py b/setup.py
index 6bdb7b9..0a2dac3 100644
--- a/setup.py
+++ b/setup.py
@@ -6,9 +6,9 @@ import os
 import re
 
 try:
-    import setuptools
+    import setuptools  # noqa: unused
 except ImportError:
-    pass # No 'develop' command, oh well.
+    pass  # No 'develop' command, oh well.
 
 base_path = os.path.dirname(__file__)
 
@@ -55,14 +55,11 @@ setup(name='urllib3',
       ],
       test_suite='test',
       extras_require={
-          'secure;python_version<="2.7"': [
-              'pyOpenSSL',
+          'secure': [
+              'pyOpenSSL>=0.13',
               'ndg-httpsclient',
               'pyasn1',
               'certifi',
           ],
-          'secure;python_version>"2.7"': [
-              'certifi',
-          ],
       },
       )
diff --git a/test/test_util.py b/test/test_util.py
index fa59ada..ef4caab 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -1,3 +1,4 @@
+import hashlib
 import warnings
 import logging
 import unittest
@@ -18,12 +19,14 @@ from urllib3.util.url import (
 from urllib3.util.ssl_ import (
     resolve_cert_reqs,
     ssl_wrap_socket,
+    _const_compare_digest_backport,
 )
 from urllib3.exceptions import (
     LocationParseError,
     TimeoutStateError,
     InsecureRequestWarning,
     SSLError,
+    SNIMissingWarning,
 )
 
 from urllib3.util import is_fp_closed, ssl_
@@ -412,3 +415,30 @@ class TestUtil(unittest.TestCase):
         ssl_wrap_socket(ssl_context=mock_context, sock=socket)
         mock_context.wrap_socket.assert_called_once_with(socket)
         ssl_.HAS_SNI = HAS_SNI
+
+    def test_ssl_wrap_socket_with_no_sni_warns(self):
+        socket = object()
+        mock_context = Mock()
+        # Ugly preservation of original value
+        HAS_SNI = ssl_.HAS_SNI
+        ssl_.HAS_SNI = False
+        with patch('warnings.warn') as warn:
+            ssl_wrap_socket(ssl_context=mock_context, sock=socket)
+        mock_context.wrap_socket.assert_called_once_with(socket)
+        ssl_.HAS_SNI = HAS_SNI
+        self.assertTrue(warn.call_count >= 1)
+        warnings = [call[0][1] for call in warn.call_args_list]
+        self.assertTrue(SNIMissingWarning in warnings)
+
+    def test_const_compare_digest_fallback(self):
+        target = hashlib.sha256(b'abcdef').digest()
+        self.assertTrue(_const_compare_digest_backport(target, target))
+
+        prefix = target[:-1]
+        self.assertFalse(_const_compare_digest_backport(target, prefix))
+
+        suffix = target + b'0'
+        self.assertFalse(_const_compare_digest_backport(target, suffix))
+
+        incorrect = hashlib.sha256(b'xyz').digest()
+        self.assertFalse(_const_compare_digest_backport(target, incorrect))
diff --git a/test/with_dummyserver/test_connectionpool.py b/test/with_dummyserver/test_connectionpool.py
index 9294adf..0f31fa0 100644
--- a/test/with_dummyserver/test_connectionpool.py
+++ b/test/with_dummyserver/test_connectionpool.py
@@ -49,6 +49,11 @@ SHORT_TIMEOUT = 0.001
 LONG_TIMEOUT = 0.01
 
 
+def wait_for_socket(ready_event):
+    ready_event.wait()
+    ready_event.clear()
+
+
 class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
 
     def test_timeout_float(self):
@@ -57,11 +62,12 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
 
         # Pool-global timeout
         pool = HTTPConnectionPool(self.host, self.port, timeout=SHORT_TIMEOUT, retries=False)
+        wait_for_socket(ready_event)
         self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
         block_event.set() # Release block
 
         # Shouldn't raise this time
-        ready_event.wait()
+        wait_for_socket(ready_event)
         block_event.set() # Pre-release block
         pool.request('GET', '/')
 
@@ -92,12 +98,13 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
         timeout = Timeout(read=SHORT_TIMEOUT)
         pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False)
 
+        wait_for_socket(ready_event)
         conn = pool._get_conn()
         self.assertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', '/')
         pool._put_conn(conn)
         block_event.set() # Release request
 
-        ready_event.wait()
+        wait_for_socket(ready_event)
         block_event.clear()
         self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
         block_event.set() # Release request
@@ -106,7 +113,7 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
         pool = HTTPConnectionPool(self.host, self.port, timeout=LONG_TIMEOUT, retries=False)
 
         conn = pool._get_conn()
-        ready_event.wait()
+        wait_for_socket(ready_event)
         now = time.time()
         self.assertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', '/', timeout=timeout)
         delta = time.time() - now
@@ -115,7 +122,7 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
         self.assertTrue(delta < LONG_TIMEOUT, "timeout was pool-level LONG_TIMEOUT rather than request-level SHORT_TIMEOUT")
         pool._put_conn(conn)
 
-        ready_event.wait()
+        wait_for_socket(ready_event)
         now = time.time()
         self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/', timeout=timeout)
         delta = time.time() - now
@@ -125,24 +132,19 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
 
         # Timeout int/float passed directly to request and _make_request should
         # raise a request timeout
-        ready_event.wait()
+        wait_for_socket(ready_event)
         self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/', timeout=SHORT_TIMEOUT)
         block_event.set() # Release request
 
-        ready_event.wait()
+        wait_for_socket(ready_event)
         conn = pool._new_conn()
         # FIXME: This assert flakes sometimes. Not sure why.
         self.assertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', '/', timeout=SHORT_TIMEOUT)
         block_event.set() # Release request
 
     def test_connect_timeout(self):
-        def noop_handler(listener):
-            return
-
-        self._start_server(noop_handler)
-
         url = '/'
-        host, port = self.host, self.port
+        host, port = TARPIT_HOST, 80
         timeout = Timeout(connect=SHORT_TIMEOUT)
 
         # Pool-global timeout
@@ -164,18 +166,15 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
         self.assertRaises(ConnectTimeoutError, pool.request, 'GET', url, timeout=timeout)
 
     def test_total_applies_connect(self):
-        def noop_handler(listener):
-            return
-
-        self._start_server(noop_handler)
+        host, port = TARPIT_HOST, 80
 
         timeout = Timeout(total=None, connect=SHORT_TIMEOUT)
-        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
+        pool = HTTPConnectionPool(host, port, timeout=timeout)
         conn = pool._get_conn()
         self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', '/')
 
         timeout = Timeout(connect=3, read=5, total=SHORT_TIMEOUT)
-        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
+        pool = HTTPConnectionPool(host, port, timeout=timeout)
         conn = pool._get_conn()
         self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', '/')
 
@@ -183,13 +182,14 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
         block_event = Event()
         ready_event = self.start_basic_handler(block_send=block_event, num=2)
 
+        wait_for_socket(ready_event)
         # This will get the socket to raise an EAGAIN on the read
         timeout = Timeout(connect=3, read=SHORT_TIMEOUT)
         pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False)
         self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
 
         block_event.set()
-        ready_event.wait()
+        wait_for_socket(ready_event)
         block_event.clear()
 
         # The connect should succeed and this should hit the read timeout
@@ -666,15 +666,15 @@ class TestConnectionPool(HTTPDummyServerTestCase):
 
     def test_cleanup_on_connection_error(self):
         '''
-        Test that connections are recycled to the pool on 
+        Test that connections are recycled to the pool on
         connection errors where no http response is received.
         '''
         poolsize = 3
         with HTTPConnectionPool(self.host, self.port, maxsize=poolsize, block=True) as http:
             self.assertEqual(http.pool.qsize(), poolsize)
 
-            # force a connection error by supplying a non-existent 
-            # url. We won't get a response for this  and so the 
+            # force a connection error by supplying a non-existent
+            # url. We won't get a response for this  and so the
             # conn won't be implicitly returned to the pool.
             self.assertRaises(MaxRetryError,
                 http.request, 'GET', '/redirect', fields={'target': '/'}, release_conn=False, retries=0)
diff --git a/test/with_dummyserver/test_https.py b/test/with_dummyserver/test_https.py
index 862ebd9..7319d7e 100644
--- a/test/with_dummyserver/test_https.py
+++ b/test/with_dummyserver/test_https.py
@@ -8,9 +8,12 @@ import warnings
 import mock
 from nose.plugins.skip import SkipTest
 
-from dummyserver.testcase import HTTPSDummyServerTestCase
+from dummyserver.testcase import (
+    HTTPSDummyServerTestCase, IPV6HTTPSDummyServerTestCase
+)
 from dummyserver.server import (DEFAULT_CA, DEFAULT_CA_BAD, DEFAULT_CERTS,
-                                NO_SAN_CERTS, NO_SAN_CA, DEFAULT_CA_DIR)
+                                NO_SAN_CERTS, NO_SAN_CA, DEFAULT_CA_DIR,
+                                IPV6_ADDR_CERTS, IPV6_ADDR_CA, HAS_IPV6)
 
 from test import (
     onlyPy26OrOlder,
@@ -35,6 +38,7 @@ from urllib3.exceptions import (
 )
 from urllib3.packages import six
 from urllib3.util.timeout import Timeout
+from urllib3.util.ssl_ import HAS_SNI
 
 
 ResourceWarning = getattr(
@@ -77,7 +81,10 @@ class TestHTTPS(HTTPSDummyServerTestCase):
                 self.assertFalse(warn.called, warn.call_args_list)
             else:
                 self.assertTrue(warn.called)
-                call, = warn.call_args_list
+                if HAS_SNI:
+                    call = warn.call_args_list[0]
+                else:
+                    call = warn.call_args_list[1]
                 error = call[0][1]
                 self.assertEqual(error, InsecurePlatformWarning)
 
@@ -176,8 +183,10 @@ class TestHTTPS(HTTPSDummyServerTestCase):
             calls = warn.call_args_list
             if sys.version_info >= (2, 7, 9):
                 category = calls[0][0][1]
-            else:
+            elif HAS_SNI:
                 category = calls[1][0][1]
+            else:
+                category = calls[2][0][1]
             self.assertEqual(category, InsecureRequestWarning)
 
     @requires_network
@@ -460,5 +469,20 @@ class TestHTTPS_NoSAN(HTTPSDummyServerTestCase):
             self.assertTrue(warn.called)
 
 
+
+class TestHTTPS_IPv6Addr(IPV6HTTPSDummyServerTestCase):
+    certs = IPV6_ADDR_CERTS
+
+    def test_strip_square_brackets_before_validating(self):
+        """Test that the fix for #760 works."""
+        if not HAS_IPV6:
+            raise SkipTest("Only runs on IPv6 systems")
+        https_pool = HTTPSConnectionPool('[::1]', self.port,
+                                         cert_reqs='CERT_REQUIRED',
+                                         ca_certs=IPV6_ADDR_CA)
+        r = https_pool.request('GET', '/')
+        self.assertEqual(r.status, 200)
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/test/with_dummyserver/test_poolmanager.py b/test/with_dummyserver/test_poolmanager.py
index 099ac52..4065ff8 100644
--- a/test/with_dummyserver/test_poolmanager.py
+++ b/test/with_dummyserver/test_poolmanager.py
@@ -69,7 +69,7 @@ class TestPoolManager(HTTPDummyServerTestCase):
         try:
             http.request('GET', '%s/redirect' % self.base_url,
                          fields={'target': cross_host_location},
-                         timeout=0.01, retries=0)
+                         timeout=1, retries=0)
             self.fail("Request succeeded instead of raising an exception like it should.")
 
         except MaxRetryError:
@@ -77,7 +77,7 @@ class TestPoolManager(HTTPDummyServerTestCase):
 
         r = http.request('GET', '%s/redirect' % self.base_url,
                          fields={'target': '%s/echo?a=b' % self.base_url_alt},
-                         timeout=0.01, retries=1)
+                         timeout=1, retries=1)
 
         self.assertEqual(r._pool.host, self.host_alt)
 
@@ -137,7 +137,7 @@ class TestPoolManager(HTTPDummyServerTestCase):
         r = http.request('POST', '%s/headers' % self.base_url)
         returned_headers = json.loads(r.data.decode())
         self.assertEqual(returned_headers.get('Foo'), 'bar')
-        
+
         r = http.request_encode_url('GET', '%s/headers' % self.base_url)
         returned_headers = json.loads(r.data.decode())
         self.assertEqual(returned_headers.get('Foo'), 'bar')
@@ -162,6 +162,12 @@ class TestPoolManager(HTTPDummyServerTestCase):
         r = http.request('GET', 'http://%s:%s/' % (self.host, self.port))
         self.assertEqual(r.status, 200)
 
+    def test_http_with_ca_cert_dir(self):
+        http = PoolManager(ca_certs='REQUIRED', ca_cert_dir='/nosuchdir')
+
+        r = http.request('GET', 'http://%s:%s/' % (self.host, self.port))
+        self.assertEqual(r.status, 200)
+
 
 class TestIPv6PoolManager(IPv6HTTPDummyServerTestCase):
     if not HAS_IPV6:
diff --git a/test/with_dummyserver/test_proxy_poolmanager.py b/test/with_dummyserver/test_proxy_poolmanager.py
index b2894a8..b37d8bb 100644
--- a/test/with_dummyserver/test_proxy_poolmanager.py
+++ b/test/with_dummyserver/test_proxy_poolmanager.py
@@ -124,7 +124,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
         try:
             http.request('GET', '%s/redirect' % self.http_url,
                          fields={'target': cross_host_location},
-                         timeout=0.1, retries=0)
+                         timeout=1, retries=0)
             self.fail("We don't want to follow redirects here.")
 
         except MaxRetryError:
@@ -132,7 +132,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
 
         r = http.request('GET', '%s/redirect' % self.http_url,
                          fields={'target': '%s/echo?a=b' % self.http_url_alt},
-                         timeout=0.1, retries=1)
+                         timeout=1, retries=1)
         self.assertNotEqual(r._pool.host, self.http_host_alt)
 
     def test_cross_protocol_redirect(self):
@@ -142,7 +142,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
         try:
             http.request('GET', '%s/redirect' % self.http_url,
                          fields={'target': cross_protocol_location},
-                         timeout=0.1, retries=0)
+                         timeout=1, retries=0)
             self.fail("We don't want to follow redirects here.")
 
         except MaxRetryError:
@@ -150,7 +150,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
 
         r = http.request('GET', '%s/redirect' % self.http_url,
                          fields={'target': '%s/echo?a=b' % self.https_url},
-                         timeout=0.1, retries=1)
+                         timeout=1, retries=1)
         self.assertEqual(r._pool.host, self.https_host)
 
     def test_headers(self):
diff --git a/test/with_dummyserver/test_socketlevel.py b/test/with_dummyserver/test_socketlevel.py
index d09002b..1e6113f 100644
--- a/test/with_dummyserver/test_socketlevel.py
+++ b/test/with_dummyserver/test_socketlevel.py
@@ -30,6 +30,7 @@ except ImportError:
     class MimeToolMessage(object):
         pass
 from threading import Event
+import select
 import socket
 import ssl
 
@@ -366,6 +367,72 @@ class TestSocketClosing(SocketDummyServerTestCase):
             self.assertRaises(ProtocolError, response.read)
             self.assertEqual(poolsize, pool.pool.qsize())
 
+    def test_connection_closed_on_read_timeout_preload_false(self):
+        timed_out = Event()
+
+        def socket_handler(listener):
+            sock = listener.accept()[0]
+
+            # Consume request
+            buf = b''
+            while not buf.endswith(b'\r\n\r\n'):
+                buf = sock.recv(65535)
+
+            # Send partial chunked response and then hang.
+            sock.send((
+                'HTTP/1.1 200 OK\r\n'
+                'Content-Type: text/plain\r\n'
+                'Transfer-Encoding: chunked\r\n'
+                '\r\n'
+                '8\r\n'
+                '12345678\r\n').encode('utf-8')
+            )
+            timed_out.wait(5)
+
+            # Expect a new request, but keep hold of the old socket to avoid
+            # leaking it. Because we don't want to hang this thread, we
+            # actually use select.select to confirm that a new request is
+            # coming in: this lets us time the thread out.
+            rlist, _, _ = select.select([listener], [], [], 1)
+            assert rlist
+            new_sock = listener.accept()[0]
+
+            # Consume request
+            buf = b''
+            while not buf.endswith(b'\r\n\r\n'):
+                buf = new_sock.recv(65535)
+
+            # Send complete chunked response.
+            new_sock.send((
+                'HTTP/1.1 200 OK\r\n'
+                'Content-Type: text/plain\r\n'
+                'Transfer-Encoding: chunked\r\n'
+                '\r\n'
+                '8\r\n'
+                '12345678\r\n'
+                '0\r\n\r\n').encode('utf-8')
+            )
+
+            new_sock.close()
+            sock.close()
+
+        self._start_server(socket_handler)
+        with HTTPConnectionPool(self.host, self.port) as pool:
+            # First request should fail.
+            response = pool.urlopen('GET', '/', retries=0,
+                                    preload_content=False,
+                                    timeout=Timeout(connect=1, read=0.001))
+            try:
+                self.assertRaises(ReadTimeoutError, response.read)
+            finally:
+                timed_out.set()
... 1081 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-urllib3.git



More information about the Python-modules-commits mailing list