[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