Skip to content

urllib3 1.24.1 to 1.25.3

mickael e edited this page Aug 16, 2019 · 1 revision
de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22  urllib3-1.24.1.tar.gz
dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232  urllib3-1.25.3.tar.gz

--- urllib3-1.24.1.tar.gz
+++ urllib3-1.25.3.tar.gz
├── metadata
│ @@ -1 +1 @@
│ -gzip compressed data, was "dist/urllib3-1.24.1.tar", last modified: Fri Nov  2 19:11:08 2018, max compression
│ +gzip compressed data, was "dist/urllib3-1.25.3.tar", last modified: Thu May 23 19:01:43 2019, max compression
│   --- urllib3-1.24.1.tar
├── +++ urllib3-1.25.3.tar
├── file list
│ │ @@ -1,152 +1,169 @@
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    29661 2018-11-02 19:08:50.000000 urllib3-1.24.1/CHANGES.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     8997 2018-10-16 17:45:39.000000 urllib3-1.24.1/CONTRIBUTORS.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1175 2018-10-05 21:00:05.000000 urllib3-1.24.1/LICENSE.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      204 2018-10-05 21:00:05.000000 urllib3-1.24.1/MANIFEST.in
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1192 2018-10-05 21:00:05.000000 urllib3-1.24.1/Makefile
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    43238 2018-11-02 19:11:08.000000 urllib3-1.24.1/PKG-INFO
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     3780 2018-10-05 21:00:05.000000 urllib3-1.24.1/README.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      292 2018-11-02 19:07:12.000000 urllib3-1.24.1/dev-requirements.txt
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4602 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/Makefile
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/_templates/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      106 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/_templates/fonts.html
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     9700 2018-10-16 17:45:39.000000 urllib3-1.24.1/docs/advanced-usage.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     8388 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/conf.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     3699 2018-10-16 17:45:39.000000 urllib3-1.24.1/docs/contributing.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1889 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/index.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4513 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/make.bat
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/reference/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1434 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/index.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      838 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/urllib3.contrib.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1539 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/urllib3.util.rst
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)       80 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/requirements.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    13677 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/user-guide.rst
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/__init__.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/certs/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      620 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/README.rst
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/98a2772e.0
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/cacert.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      891 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1827 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.no_san.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1391 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.csr
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      887 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      993 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client_bad.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      887 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_intermediate.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1953 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_intermediate.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      936 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_no_intermediate.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      887 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/intermediate.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1054 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/intermediate.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2148 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.combined.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.crt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1330 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.csr
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1265 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ip_san.crt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      956 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ipv6addr.crt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1679 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ipv6addr.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      891 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.key
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      561 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.key.org
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      936 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.no_san.crt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      696 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.no_san.csr
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    11886 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/handlers.py
│ │ --rwxr-xr-x   0 theaflowers (297975) primarygroup (297975)     4756 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/proxy.py
│ │ --rwxr-xr-x   0 theaflowers (297975) primarygroup (297975)     9430 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/server.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     6470 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/testcase.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      550 2018-11-02 19:11:08.000000 urllib3-1.24.1/setup.cfg
│ │ --rwxr-xr-x   0 theaflowers (297975) primarygroup (297975)     2684 2018-10-16 17:45:39.000000 urllib3-1.24.1/setup.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2722 2018-11-02 19:09:02.000000 urllib3-1.24.1/src/urllib3/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    10746 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/_collections.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    13839 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/connection.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    35097 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/connectionpool.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/contrib/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      717 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_appengine_environ.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    17560 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/bindings.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    12162 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/low_level.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    10914 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/appengine.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4459 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/ntlmpool.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    15806 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/pyopenssl.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    30309 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/securetransport.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     6391 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/socks.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     6604 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/exceptions.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5943 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/fields.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2436 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/filepost.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      109 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/__init__.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/backports/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/backports/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1456 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/backports/makefile.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    30098 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/six.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      688 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5683 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    16853 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/poolmanager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5991 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/request.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    25609 2018-11-02 19:07:12.000000 urllib3-1.24.1/src/urllib3/response.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/util/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1044 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4639 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/connection.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      497 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/queue.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     3705 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/request.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2586 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/response.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    15105 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/retry.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    13143 2018-11-02 19:07:12.000000 urllib3-1.24.1/src/urllib3/util/ssl_.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     9757 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/timeout.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     6487 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/url.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5403 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/wait.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    43238 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/PKG-INFO
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     3840 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/SOURCES.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        1 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/dependency_links.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      113 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/requires.txt
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        8 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/top_level.txt
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4210 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/__init__.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/appengine/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2231 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/appengine/conftest.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     6435 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/test_gae_manager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2547 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/test_urlfetch.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2086 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/benchmark.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/contrib/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/duplicate_san.pem
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2675 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/contrib/test_pyopenssl.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1760 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/test_pyopenssl_dependencies.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      992 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/test_securetransport.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    23210 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/contrib/test_socks.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5702 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/port_helpers.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2424 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/socketpair_helper.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    10471 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_collections.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1426 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_compatibility.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1875 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_connection.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    17446 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_connectionpool.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1390 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_exceptions.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2631 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_fields.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4201 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_filepost.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2219 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_no_ssl.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    13688 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_poolmanager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     1672 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_proxymanager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      808 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_queue_monkeypatch.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    26999 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_response.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    10713 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_retry.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     2656 2018-11-02 19:07:12.000000 urllib3-1.24.1/test/test_ssl.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    22603 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_util.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     5506 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_wait.py
│ │ -drwxr-xr-x   0 theaflowers (297975) primarygroup (297975)        0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/with_dummyserver/
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)        0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/with_dummyserver/__init__.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)     4002 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_chunked_transfer.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    41165 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_connectionpool.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    26075 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_https.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)      933 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_no_ssl.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    10641 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_poolmanager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    15183 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_proxy_poolmanager.py
│ │ --rw-r--r--   0 theaflowers (297975) primarygroup (297975)    53266 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_socketlevel.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    31939 2019-05-23 19:01:31.000000 urllib3-1.25.3/CHANGES.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     9141 2019-05-23 19:01:31.000000 urllib3-1.25.3/CONTRIBUTORS.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1115 2019-05-23 19:01:31.000000 urllib3-1.25.3/LICENSE.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      204 2019-05-23 19:01:31.000000 urllib3-1.25.3/MANIFEST.in
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1192 2019-05-23 19:01:31.000000 urllib3-1.25.3/Makefile
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    47286 2019-05-23 19:01:43.000000 urllib3-1.25.3/PKG-INFO
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4683 2019-05-23 19:01:31.000000 urllib3-1.25.3/README.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      359 2019-05-23 19:01:31.000000 urllib3-1.25.3/dev-requirements.txt
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4602 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/Makefile
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/_templates/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      106 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/_templates/fonts.html
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10764 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/advanced-usage.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     8389 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/conf.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5304 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/contributing.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1889 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/index.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4513 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/make.bat
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/reference/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1434 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/index.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      838 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/urllib3.contrib.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1539 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/urllib3.util.rst
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)       62 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/requirements.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    13781 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/user-guide.rst
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/__init__.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/certs/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      620 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/README.rst
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/98a2772e.0
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/cacert.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      891 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1827 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.no_san.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1391 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.csr
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      993 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_bad.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_intermediate.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1953 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_intermediate.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      936 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_no_intermediate.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      986 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_password.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/intermediate.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1054 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/intermediate.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2148 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.combined.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.crt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1330 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.csr
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1265 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ip_san.crt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      924 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6_san.crt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      956 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6addr.crt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1679 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6addr.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      891 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      561 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.key.org
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      936 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.no_san.crt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      696 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.no_san.csr
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      986 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server_password.key
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10657 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/handlers.py
│ │ +-rwxrwxr-x   0 travis    (2000) travis    (2000)     4756 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/proxy.py
│ │ +-rwxrwxr-x   0 travis    (2000) travis    (2000)     9759 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/server.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     6470 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/testcase.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      550 2019-05-23 19:01:43.000000 urllib3-1.25.3/setup.cfg
│ │ +-rwxrwxr-x   0 travis    (2000) travis    (2000)     2901 2019-05-23 19:01:31.000000 urllib3-1.25.3/setup.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2721 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10746 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/_collections.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    15001 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/connection.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    35307 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/connectionpool.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/contrib/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      717 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_appengine_environ.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    17576 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/bindings.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    12162 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/low_level.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10914 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/appengine.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4459 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/ntlmpool.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    16451 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/pyopenssl.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    32826 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/securetransport.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     7012 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/socks.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     6604 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/exceptions.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     8575 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/fields.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2436 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/filepost.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      109 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/__init__.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/backports/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/backports/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1456 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/backports/makefile.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1562 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    13214 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/_mixin.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     9081 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/abnf_regexp.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     3887 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/api.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     9577 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/builder.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1513 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/compat.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     3775 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/exceptions.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5466 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/iri.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4094 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/misc.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5259 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/normalizers.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    14654 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/parseresult.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5227 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/uri.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    13854 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/validators.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    30098 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/six.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      688 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5683 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    17050 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/poolmanager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5991 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/request.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    27171 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/response.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/util/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1082 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4639 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/connection.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      497 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/queue.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     3832 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/request.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2586 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/response.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    15150 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/retry.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    13786 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/ssl_.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     9768 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/timeout.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     9810 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/url.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5403 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/wait.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    47286 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/PKG-INFO
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4476 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/SOURCES.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        1 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/dependency_links.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      173 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/requires.txt
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        8 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/top_level.txt
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     6629 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/__init__.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/appengine/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2231 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/conftest.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     6435 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/test_gae_manager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2547 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/test_urlfetch.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2086 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/benchmark.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/contrib/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/duplicate_san.pem
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2815 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_pyopenssl.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1945 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_pyopenssl_dependencies.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1061 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_securetransport.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    23243 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_socks.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5702 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/port_helpers.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2424 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/socketpair_helper.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10471 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_collections.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1426 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_compatibility.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1875 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_connection.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    17459 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_connectionpool.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1390 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_exceptions.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4206 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_fields.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4201 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_filepost.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     2219 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_no_ssl.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    13688 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_poolmanager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     1672 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_proxymanager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      808 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_queue_monkeypatch.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    29090 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_response.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    10713 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_retry.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4074 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_ssl.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    29188 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_util.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     5506 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_wait.py
│ │ +drwxrwxr-x   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/with_dummyserver/
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)        0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/__init__.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)     4002 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_chunked_transfer.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    41843 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_connectionpool.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    29216 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_https.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)      951 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_no_ssl.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    11616 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_poolmanager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    14973 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_proxy_poolmanager.py
│ │ +-rw-rw-r--   0 travis    (2000) travis    (2000)    58742 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_socketlevel.py
│   --- urllib3-1.24.1/dummyserver/certs/server.ip_san.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.ip_san.crt
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_connectionpool.py
├── +++ urllib3-1.25.3/test/test_connectionpool.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -1,9 +1,10 @@
│ │  from __future__ import absolute_import
│ │  
│ │ +import ssl
│ │  import pytest
│ │  
│ │  from urllib3.connectionpool import (
│ │      connection_from_url,
│ │      HTTPConnection,
│ │      HTTPConnectionPool,
│ │      HTTPSConnectionPool,
│ │ @@ -346,15 +347,15 @@
│ │      def test_absolute_url(self):
│ │          with connection_from_url('http://google.com:80') as c:
│ │              assert 'http://google.com:80/path?query=foo' == c._absolute_url('path?query=foo')
│ │  
│ │      def test_ca_certs_default_cert_required(self):
│ │          with connection_from_url('https://google.com:80', ca_certs=DEFAULT_CA) as pool:
│ │              conn = pool._get_conn()
│ │ -            assert conn.cert_reqs == 'CERT_REQUIRED'
│ │ +            assert conn.cert_reqs == ssl.CERT_REQUIRED
│ │  
│ │      def test_cleanup_on_extreme_connection_error(self):
│ │          """
│ │          This test validates that we clean up properly even on exceptions that
│ │          we'd not otherwise catch, i.e. those that inherit from BaseException
│ │          like KeyboardInterrupt or gevent.Timeout. See #805 for more details.
│ │          """
│   --- urllib3-1.24.1/test/contrib/duplicate_san.pem
├── +++ urllib3-1.25.3/test/contrib/duplicate_san.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_poolmanager.py
├── +++ urllib3-1.25.3/test/test_poolmanager.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/make.bat
├── +++ urllib3-1.25.3/docs/make.bat
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_connection.py
├── +++ urllib3-1.25.3/test/test_connection.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/util/timeout.py
├── +++ urllib3-1.25.3/src/urllib3/util/timeout.py
│┄ Files similar despite different names (difference score: 1)
│ │ @@ -127,15 +127,16 @@
│ │                               "int, float or None." % (name, value))
│ │  
│ │          try:
│ │              if value <= 0:
│ │                  raise ValueError("Attempted to set %s timeout to %s, but the "
│ │                                   "timeout cannot be set to a value less "
│ │                                   "than or equal to 0." % (name, value))
│ │ -        except TypeError:  # Python 3
│ │ +        except TypeError:
│ │ +            # Python 3
│ │              raise ValueError("Timeout value %s was %s, but it must be an "
│ │                               "int, float or None." % (name, value))
│ │  
│ │          return value
│ │  
│ │      @classmethod
│ │      def from_float(cls, timeout):
│   --- urllib3-1.24.1/setup.py
├── +++ urllib3-1.25.3/setup.py
│┄ Files similar despite different names (difference score: 15)
│ │ @@ -31,46 +31,51 @@
│ │            'Programming Language :: Python',
│ │            'Programming Language :: Python :: 2',
│ │            'Programming Language :: Python :: 2.7',
│ │            'Programming Language :: Python :: 3',
│ │            'Programming Language :: Python :: 3.4',
│ │            'Programming Language :: Python :: 3.5',
│ │            'Programming Language :: Python :: 3.6',
│ │ +          'Programming Language :: Python :: 3.7',
│ │ +          'Programming Language :: Python :: 3.8',
│ │            'Programming Language :: Python :: Implementation :: CPython',
│ │            'Programming Language :: Python :: Implementation :: PyPy',
│ │            'Topic :: Internet :: WWW/HTTP',
│ │            'Topic :: Software Development :: Libraries',
│ │        ],
│ │        keywords='urllib httplib threadsafe filepost http https ssl pooling',
│ │        author='Andrey Petrov',
│ │        author_email='[email protected]',
│ │        url='https://urllib3.readthedocs.io/',
│ │        license='MIT',
│ │        packages=['urllib3',
│ │                  'urllib3.packages', 'urllib3.packages.ssl_match_hostname',
│ │ -                'urllib3.packages.backports', 'urllib3.contrib',
│ │ -                'urllib3.contrib._securetransport', 'urllib3.util',
│ │ -                ],
│ │ +                'urllib3.packages.backports', 'urllib3.packages.rfc3986',
│ │ +                'urllib3.contrib', 'urllib3.contrib._securetransport',
│ │ +                'urllib3.util'],
│ │        package_dir={'': 'src'},
│ │        requires=[],
│ │        python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4",
│ │        tests_require=[
│ │            # These are a less-specific subset of dev-requirements.txt, for the
│ │            # convenience of distro package maintainers.
│ │            'pytest',
│ │            'mock',
│ │            'tornado',
│ │        ],
│ │        test_suite='test',
│ │        extras_require={
│ │ +          'brotli': [
│ │ +              'brotlipy>=0.6.0',
│ │ +          ],
│ │            'secure': [
│ │ -              'pyOpenSSL >= 0.14',
│ │ +              'pyOpenSSL>=0.14',
│ │                'cryptography>=1.3.4',
│ │                'idna>=2.0.0',
│ │                'certifi',
│ │ -              "ipaddress",
│ │ +              "ipaddress; python_version=='2.7'",
│ │            ],
│ │            'socks': [
│ │                'PySocks>=1.5.6,<2.0,!=1.5.7',
│ │            ]
│ │        },
│ │        )
│   --- urllib3-1.24.1/test/test_retry.py
├── +++ urllib3-1.25.3/test/test_retry.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -249,13 +249,13 @@
│ │          retry = Retry()
│ │          with pytest.raises(ReadTimeoutError):
│ │              retry.increment(method='POST', error=error)
│ │  
│ │      def test_retry_default_remove_headers_on_redirect(self):
│ │          retry = Retry()
│ │  
│ │ -        assert list(retry.remove_headers_on_redirect) == ['Authorization']
│ │ +        assert list(retry.remove_headers_on_redirect) == ['authorization']
│ │  
│ │      def test_retry_set_remove_headers_on_redirect(self):
│ │          retry = Retry(remove_headers_on_redirect=['X-API-Secret'])
│ │  
│ │ -        assert list(retry.remove_headers_on_redirect) == ['X-API-Secret']
│ │ +        assert list(retry.remove_headers_on_redirect) == ['x-api-secret']
│   --- urllib3-1.24.1/src/urllib3/_collections.py
├── +++ urllib3-1.25.3/src/urllib3/_collections.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/contrib/test_socks.py
├── +++ urllib3-1.25.3/test/contrib/test_socks.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -1,14 +1,14 @@
│ │  import threading
│ │  import socket
│ │  
│ │  from urllib3.contrib import socks
│ │  from urllib3.exceptions import ConnectTimeoutError, NewConnectionError
│ │  
│ │ -from dummyserver.server import DEFAULT_CERTS
│ │ +from dummyserver.server import DEFAULT_CERTS, DEFAULT_CA
│ │  from dummyserver.testcase import IPV4SocketDummyServerTestCase
│ │  
│ │  import pytest
│ │  
│ │  try:
│ │      import ssl
│ │      from urllib3.util import ssl_ as better_ssl
│ │ @@ -711,14 +711,14 @@
│ │                          b'Content-Length: 0\r\n'
│ │                          b'\r\n')
│ │              tls.close()
│ │              sock.close()
│ │  
│ │          self._start_server(request_handler)
│ │          proxy_url = "socks5h://%s:%s" % (self.host, self.port)
│ │ -        pm = socks.SOCKSProxyManager(proxy_url)
│ │ +        pm = socks.SOCKSProxyManager(proxy_url, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(pm.clear)
│ │          response = pm.request('GET', 'https://localhost')
│ │  
│ │          self.assertEqual(response.status, 200)
│ │          self.assertEqual(response.data, b'')
│ │          self.assertEqual(response.headers['Server'], 'SocksTestServer')
│   --- urllib3-1.24.1/src/urllib3/util/retry.py
├── +++ urllib3-1.25.3/src/urllib3/util/retry.py
│┄ Files similar despite different names (difference score: 1)
│ │ @@ -175,15 +175,16 @@
│ │          self.status_forcelist = status_forcelist or set()
│ │          self.method_whitelist = method_whitelist
│ │          self.backoff_factor = backoff_factor
│ │          self.raise_on_redirect = raise_on_redirect
│ │          self.raise_on_status = raise_on_status
│ │          self.history = history or tuple()
│ │          self.respect_retry_after_header = respect_retry_after_header
│ │ -        self.remove_headers_on_redirect = remove_headers_on_redirect
│ │ +        self.remove_headers_on_redirect = frozenset([
│ │ +            h.lower() for h in remove_headers_on_redirect])
│ │  
│ │      def new(self, **kw):
│ │          params = dict(
│ │              total=self.total,
│ │              connect=self.connect, read=self.read, redirect=self.redirect, status=self.status,
│ │              method_whitelist=self.method_whitelist,
│ │              status_forcelist=self.status_forcelist,
│   --- urllib3-1.24.1/src/urllib3/contrib/_securetransport/low_level.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_securetransport/low_level.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/user-guide.rst
├── +++ urllib3-1.25.3/docs/user-guide.rst
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -136,15 +136,15 @@
│ │      ...     fields={'field': 'value'})
│ │      >>> json.loads(r.data.decode('utf-8'))['form']
│ │      {'field': 'value'}
│ │  
│ │  JSON
│ │  ~~~~
│ │  
│ │ -You can sent JSON a request by specifying the encoded data as the ``body``
│ │ +You can send a JSON request by specifying the encoded data as the ``body``
│ │  argument and setting the ``Content-Type`` header when calling
│ │  :meth:`~poolmanager.PoolManager.request`::
│ │  
│ │      >>> import json
│ │      >>> data = {'attribute': 'value'}
│ │      >>> encoded_data = json.dumps(data).encode('utf-8')
│ │      >>> r = http.request(
│ │ @@ -198,19 +198,23 @@
│ │      b'...'
│ │  
│ │  .. _ssl:
│ │  
│ │  Certificate verification
│ │  ------------------------
│ │  
│ │ -It is highly recommended to always use SSL certificate verification.
│ │ -**By default, urllib3 does not verify HTTPS requests**.
│ │ + .. note:: *New in version 1.25*
│ │  
│ │ -In order to enable verification you will need a set of root certificates. The easiest
│ │ -and most reliable method is to use the `certifi <https://certifi.io/>`_ package which provides Mozilla's root certificate bundle::
│ │ +    HTTPS connections are now verified by default (``cert_reqs = 'CERT_REQUIRED'``).
│ │ +
│ │ +While you can disable certification verification, it is highly recommend to leave it on.
│ │ +
│ │ +Unless otherwise specified urllib3 will try to load the default system certificate stores.
│ │ +The most reliable cross-platform method is to use the `certifi <https://certifi.io/>`_
│ │ +package which provides Mozilla's root certificate bundle::
│ │  
│ │      pip install certifi
│ │  
│ │  You can also install certifi along with urllib3 by using the ``secure``
│ │  extra::
│ │  
│ │      pip install urllib3[secure]
│   --- urllib3-1.24.1/test/socketpair_helper.py
├── +++ urllib3-1.25.3/test/socketpair_helper.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/util/ssl_.py
├── +++ urllib3-1.25.3/src/urllib3/util/ssl_.py
│┄ Files similar despite different names (difference score: 24)
│ │ @@ -1,18 +1,19 @@
│ │  from __future__ import absolute_import
│ │  import errno
│ │  import warnings
│ │  import hmac
│ │ -import socket
│ │ +import re
│ │  
│ │  from binascii import hexlify, unhexlify
│ │  from hashlib import md5, sha1, sha256
│ │  
│ │  from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning
│ │  from ..packages import six
│ │ +from ..packages.rfc3986 import abnf_regexp
│ │  
│ │  
│ │  SSLContext = None
│ │  HAS_SNI = False
│ │  IS_PYOPENSSL = False
│ │  IS_SECURETRANSPORT = False
│ │  
│ │ @@ -36,88 +37,86 @@
│ │          result |= l ^ r
│ │      return result == 0
│ │  
│ │  
│ │  _const_compare_digest = getattr(hmac, 'compare_digest',
│ │                                  _const_compare_digest_backport)
│ │  
│ │ +# Borrow rfc3986's regular expressions for IPv4
│ │ +# and IPv6 addresses for use in is_ipaddress()
│ │ +_IP_ADDRESS_REGEX = re.compile(
│ │ +    r'^(?:%s|%s|%s)$' % (
│ │ +        abnf_regexp.IPv4_RE,
│ │ +        abnf_regexp.IPv6_RE,
│ │ +        abnf_regexp.IPv6_ADDRZ_RFC4007_RE
│ │ +    )
│ │ +)
│ │  
│ │  try:  # Test for SSL features
│ │      import ssl
│ │ -    from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
│ │ +    from ssl import wrap_socket, CERT_REQUIRED
│ │      from ssl import HAS_SNI  # Has SNI?
│ │  except ImportError:
│ │      pass
│ │  
│ │ +try:  # Platform-specific: Python 3.6
│ │ +    from ssl import PROTOCOL_TLS
│ │ +    PROTOCOL_SSLv23 = PROTOCOL_TLS
│ │ +except ImportError:
│ │ +    try:
│ │ +        from ssl import PROTOCOL_SSLv23 as PROTOCOL_TLS
│ │ +        PROTOCOL_SSLv23 = PROTOCOL_TLS
│ │ +    except ImportError:
│ │ +        PROTOCOL_SSLv23 = PROTOCOL_TLS = 2
│ │ +
│ │  
│ │  try:
│ │      from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION
│ │  except ImportError:
│ │      OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000
│ │      OP_NO_COMPRESSION = 0x20000
│ │  
│ │  
│ │ -# Python 2.7 doesn't have inet_pton on non-Linux so we fallback on inet_aton in
│ │ -# those cases. This means that we can only detect IPv4 addresses in this case.
│ │ -if hasattr(socket, 'inet_pton'):
│ │ -    inet_pton = socket.inet_pton
│ │ -else:
│ │ -    # Maybe we can use ipaddress if the user has urllib3[secure]?
│ │ -    try:
│ │ -        import ipaddress
│ │ -
│ │ -        def inet_pton(_, host):
│ │ -            if isinstance(host, bytes):
│ │ -                host = host.decode('ascii')
│ │ -            return ipaddress.ip_address(host)
│ │ -
│ │ -    except ImportError:  # Platform-specific: Non-Linux
│ │ -        def inet_pton(_, host):
│ │ -            return socket.inet_aton(host)
│ │ -
│ │ -
│ │  # A secure default.
│ │  # Sources for more information on TLS ciphers:
│ │  #
│ │  # - https://wiki.mozilla.org/Security/Server_Side_TLS
│ │  # - https://www.ssllabs.com/projects/best-practices/index.html
│ │  # - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
│ │  #
│ │  # The general intent is:
│ │ -# - Prefer TLS 1.3 cipher suites
│ │  # - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE),
│ │  # - prefer ECDHE over DHE for better performance,
│ │  # - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and
│ │  #   security,
│ │  # - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
│ │ -# - disable NULL authentication, MD5 MACs and DSS for security reasons.
│ │ +# - disable NULL authentication, MD5 MACs, DSS, and other
│ │ +#   insecure ciphers for security reasons.
│ │ +# - NOTE: TLS 1.3 cipher suites are managed through a different interface
│ │ +#   not exposed by CPython (yet!) and are enabled by default if they're available.
│ │  DEFAULT_CIPHERS = ':'.join([
│ │ -    'TLS13-AES-256-GCM-SHA384',
│ │ -    'TLS13-CHACHA20-POLY1305-SHA256',
│ │ -    'TLS13-AES-128-GCM-SHA256',
│ │ +    'ECDHE+AESGCM',
│ │ +    'ECDHE+CHACHA20',
│ │ +    'DHE+AESGCM',
│ │ +    'DHE+CHACHA20',
│ │      'ECDH+AESGCM',
│ │ -    'ECDH+CHACHA20',
│ │      'DH+AESGCM',
│ │ -    'DH+CHACHA20',
│ │ -    'ECDH+AES256',
│ │ -    'DH+AES256',
│ │ -    'ECDH+AES128',
│ │ +    'ECDH+AES',
│ │      'DH+AES',
│ │      'RSA+AESGCM',
│ │      'RSA+AES',
│ │      '!aNULL',
│ │      '!eNULL',
│ │      '!MD5',
│ │ +    '!DSS',
│ │  ])
│ │  
│ │  try:
│ │      from ssl import SSLContext  # Modern SSL?
│ │  except ImportError:
│ │ -    import sys
│ │ -
│ │      class SSLContext(object):  # Platform-specific: Python 2
│ │          def __init__(self, protocol_version):
│ │              self.protocol = protocol_version
│ │              # Use default values from a real SSLContext
│ │              self.check_hostname = False
│ │              self.verify_mode = ssl.CERT_NONE
│ │              self.ca_certs = None
│ │ @@ -195,15 +194,15 @@
│ │      If given a string it is assumed to be the name of the constant in the
│ │      :mod:`ssl` module or its abbreviation.
│ │      (So you can specify `REQUIRED` instead of `CERT_REQUIRED`.
│ │      If it's neither `None` nor a string we assume it is already the numeric
│ │      constant which can directly be passed to wrap_socket.
│ │      """
│ │      if candidate is None:
│ │ -        return CERT_NONE
│ │ +        return CERT_REQUIRED
│ │  
│ │      if isinstance(candidate, str):
│ │          res = getattr(ssl, candidate, None)
│ │          if res is None:
│ │              res = getattr(ssl, 'CERT_' + candidate)
│ │          return res
│ │  
│ │ @@ -211,15 +210,15 @@
│ │  
│ │  
│ │  def resolve_ssl_version(candidate):
│ │      """
│ │      like resolve_cert_reqs
│ │      """
│ │      if candidate is None:
│ │ -        return PROTOCOL_SSLv23
│ │ +        return PROTOCOL_TLS
│ │  
│ │      if isinstance(candidate, str):
│ │          res = getattr(ssl, candidate, None)
│ │          if res is None:
│ │              res = getattr(ssl, 'PROTOCOL_' + candidate)
│ │          return res
│ │  
│ │ @@ -257,15 +256,15 @@
│ │          ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``.
│ │      :param ciphers:
│ │          Which cipher suites to allow the server to select.
│ │      :returns:
│ │          Constructed SSLContext object with specified options
│ │      :rtype: SSLContext
│ │      """
│ │ -    context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23)
│ │ +    context = SSLContext(ssl_version or PROTOCOL_TLS)
│ │  
│ │      context.set_ciphers(ciphers or DEFAULT_CIPHERS)
│ │  
│ │      # Setting the default here, as we may have no ssl module on import
│ │      cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
│ │  
│ │      if options is None:
│ │ @@ -287,15 +286,15 @@
│ │          context.check_hostname = False
│ │      return context
│ │  
│ │  
│ │  def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
│ │                      ca_certs=None, server_hostname=None,
│ │                      ssl_version=None, ciphers=None, ssl_context=None,
│ │ -                    ca_cert_dir=None):
│ │ +                    ca_cert_dir=None, key_password=None):
│ │      """
│ │      All arguments except for server_hostname, ssl_context, and ca_cert_dir have
│ │      the same meaning as they do when using :func:`ssl.wrap_socket`.
│ │  
│ │      :param server_hostname:
│ │          When SNI is supported, the expected hostname of the certificate
│ │      :param ssl_context:
│ │ @@ -303,14 +302,16 @@
│ │          be created using :func:`create_urllib3_context`.
│ │      :param ciphers:
│ │          A string of ciphers we wish the client to support.
│ │      :param ca_cert_dir:
│ │          A directory containing CA certificates in multiple separate files, as
│ │          supported by OpenSSL's -CApath flag or the capath argument to
│ │          SSLContext.load_verify_locations().
│ │ +    :param key_password:
│ │ +        Optional password if the keyfile is encrypted.
│ │      """
│ │      context = ssl_context
│ │      if context is None:
│ │          # Note: This branch of code and all the variables in it are no longer
│ │          # used by urllib3 itself. We should consider deprecating and removing
│ │          # this code.
│ │          context = create_urllib3_context(ssl_version, cert_reqs,
│ │ @@ -323,20 +324,30 @@
│ │              raise SSLError(e)
│ │          # Py33 raises FileNotFoundError which subclasses OSError
│ │          # These are not equivalent unless we check the errno attribute
│ │          except OSError as e:  # Platform-specific: Python 3.3 and beyond
│ │              if e.errno == errno.ENOENT:
│ │                  raise SSLError(e)
│ │              raise
│ │ -    elif getattr(context, 'load_default_certs', None) is not None:
│ │ +
│ │ +    elif ssl_context is None and hasattr(context, 'load_default_certs'):
│ │          # try to load OS default certs; works well on Windows (require Python3.4+)
│ │          context.load_default_certs()
│ │  
│ │ +    # Attempt to detect if we get the goofy behavior of the
│ │ +    # keyfile being encrypted and OpenSSL asking for the
│ │ +    # passphrase via the terminal and instead error out.
│ │ +    if keyfile and key_password is None and _is_key_file_encrypted(keyfile):
│ │ +        raise SSLError("Client private key is encrypted, password is required")
│ │ +
│ │      if certfile:
│ │ -        context.load_cert_chain(certfile, keyfile)
│ │ +        if key_password is None:
│ │ +            context.load_cert_chain(certfile, keyfile)
│ │ +        else:
│ │ +            context.load_cert_chain(certfile, keyfile, key_password)
│ │  
│ │      # If we detect server_hostname is an IP address then the SNI
│ │      # extension should not be used according to RFC3546 Section 3.1
│ │      # We shouldn't warn the user if SNI isn't available but we would
│ │      # not be using SNI anyways due to IP address for server_hostname.
│ │      if ((server_hostname is not None and not is_ipaddress(server_hostname))
│ │              or IS_SECURETRANSPORT):
│ │ @@ -354,28 +365,28 @@
│ │              SNIMissingWarning
│ │          )
│ │  
│ │      return context.wrap_socket(sock)
│ │  
│ │  
│ │  def is_ipaddress(hostname):
│ │ -    """Detects whether the hostname given is an IP address.
│ │ +    """Detects whether the hostname given is an IPv4 or IPv6 address.
│ │ +    Also detects IPv6 addresses with Zone IDs.
│ │  
│ │      :param str hostname: Hostname to examine.
│ │      :return: True if the hostname is an IP address, False otherwise.
│ │      """
│ │      if six.PY3 and isinstance(hostname, bytes):
│ │          # IDN A-label bytes are ASCII compatible.
│ │          hostname = hostname.decode('ascii')
│ │ +    return _IP_ADDRESS_REGEX.match(hostname) is not None
│ │  
│ │ -    families = [socket.AF_INET]
│ │ -    if hasattr(socket, 'AF_INET6'):
│ │ -        families.append(socket.AF_INET6)
│ │  
│ │ -    for af in families:
│ │ -        try:
│ │ -            inet_pton(af, hostname)
│ │ -        except (socket.error, ValueError, OSError):
│ │ -            pass
│ │ -        else:
│ │ -            return True
│ │ +def _is_key_file_encrypted(key_file):
│ │ +    """Detects if a key file is encrypted or not."""
│ │ +    with open(key_file, 'r') as f:
│ │ +        for line in f:
│ │ +            # Look for Proc-Type: 4,ENCRYPTED
│ │ +            if 'ENCRYPTED' in line:
│ │ +                return True
│ │ +
│ │      return False
│   --- urllib3-1.24.1/src/urllib3/util/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/util/__init__.py
│┄ Files similar despite different names (difference score: 52)
│ │ @@ -8,14 +8,15 @@
│ │      HAS_SNI,
│ │      IS_PYOPENSSL,
│ │      IS_SECURETRANSPORT,
│ │      assert_fingerprint,
│ │      resolve_cert_reqs,
│ │      resolve_ssl_version,
│ │      ssl_wrap_socket,
│ │ +    PROTOCOL_TLS,
│ │  )
│ │  from .timeout import (
│ │      current_time,
│ │      Timeout,
│ │  )
│ │  
│ │  from .retry import Retry
│ │ @@ -31,14 +32,15 @@
│ │  )
│ │  
│ │  __all__ = (
│ │      'HAS_SNI',
│ │      'IS_PYOPENSSL',
│ │      'IS_SECURETRANSPORT',
│ │      'SSLContext',
│ │ +    'PROTOCOL_TLS',
│ │      'Retry',
│ │      'Timeout',
│ │      'Url',
│ │      'assert_fingerprint',
│ │      'current_time',
│ │      'is_connection_dropped',
│ │      'is_fp_closed',
│   --- urllib3-1.24.1/src/urllib3/util/request.py
├── +++ urllib3-1.25.3/src/urllib3/util/request.py
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -1,14 +1,21 @@
│ │  from __future__ import absolute_import
│ │  from base64 import b64encode
│ │  
│ │  from ..packages.six import b, integer_types
│ │  from ..exceptions import UnrewindableBodyError
│ │  
│ │  ACCEPT_ENCODING = 'gzip,deflate'
│ │ +try:
│ │ +    import brotli as _unused_module_brotli  # noqa: F401
│ │ +except ImportError:
│ │ +    pass
│ │ +else:
│ │ +    ACCEPT_ENCODING += ',br'
│ │ +
│ │  _FAILEDTELL = object()
│ │  
│ │  
│ │  def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
│ │                   basic_auth=None, proxy_basic_auth=None, disable_cache=None):
│ │      """
│ │      Shortcuts for generating request headers.
│   --- urllib3-1.24.1/src/urllib3/packages/six.py
├── +++ urllib3-1.25.3/src/urllib3/packages/six.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client.csr
├── +++ urllib3-1.25.3/dummyserver/certs/client.csr
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/server.py
├── +++ urllib3-1.25.3/dummyserver/server.py
│┄ Files similar despite different names (difference score: 13)
│ │ @@ -42,31 +42,38 @@
│ │                      commonName=u'SnakeOilClient',
│ │                      emailAddress=u'[email protected]'),
│ │  }
│ │  DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS = {
│ │      'certfile': os.path.join(CERTS_PATH, 'client_no_intermediate.pem'),
│ │      'keyfile': os.path.join(CERTS_PATH, 'client_intermediate.key'),
│ │  }
│ │ +PASSWORD_KEYFILE = os.path.join(CERTS_PATH, 'server_password.key')
│ │ +PASSWORD_CLIENT_KEYFILE = os.path.join(CERTS_PATH, 'client_password.key')
│ │  NO_SAN_CERTS = {
│ │      'certfile': os.path.join(CERTS_PATH, 'server.no_san.crt'),
│ │      'keyfile': DEFAULT_CERTS['keyfile']
│ │  }
│ │  IP_SAN_CERTS = {
│ │      'certfile': os.path.join(CERTS_PATH, 'server.ip_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'),
│ │  }
│ │ +IPV6_SAN_CERTS = {
│ │ +    'certfile': os.path.join(CERTS_PATH, 'server.ipv6_san.crt'),
│ │ +    'keyfile': DEFAULT_CERTS['keyfile']
│ │ +}
│ │  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')
│ │ +IPV6_SAN_CA = os.path.join(CERTS_PATH, 'server.ipv6_san.crt')
│ │  COMBINED_CERT_AND_KEY = os.path.join(CERTS_PATH, 'server.combined.pem')
│ │  
│ │  
│ │  def _has_ipv6(host):
│ │      """ Returns True if the system can bind an IPv6 address. """
│ │      sock = None
│ │      has_ipv6 = False
│   --- urllib3-1.24.1/test/test_filepost.py
├── +++ urllib3-1.25.3/test/test_filepost.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/with_dummyserver/test_socketlevel.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_socketlevel.py
│┄ Files similar despite different names (difference score: 19)
│ │ @@ -8,37 +8,43 @@
│ │          ProxyError,
│ │          ReadTimeoutError,
│ │          SSLError,
│ │          ProtocolError,
│ │  )
│ │  from urllib3.response import httplib
│ │  from urllib3.util.ssl_ import HAS_SNI
│ │ +from urllib3.util import ssl_
│ │  from urllib3.util.timeout import Timeout
│ │  from urllib3.util.retry import Retry
│ │  from urllib3._collections import HTTPHeaderDict
│ │  
│ │  from dummyserver.testcase import SocketDummyServerTestCase, consume_socket
│ │  from dummyserver.server import (
│ │ -    DEFAULT_CERTS, DEFAULT_CA, COMBINED_CERT_AND_KEY, get_unreachable_address)
│ │ +    DEFAULT_CERTS, DEFAULT_CA, COMBINED_CERT_AND_KEY,
│ │ +    PASSWORD_KEYFILE, get_unreachable_address
│ │ +)
│ │  
│ │  from .. import onlyPy3, LogRecorder
│ │  
│ │  try:
│ │      from mimetools import Message as MimeToolMessage
│ │  except ImportError:
│ │      class MimeToolMessage(object):
│ │          pass
│ │  from collections import OrderedDict
│ │  from threading import Event
│ │  import select
│ │  import socket
│ │  import ssl
│ │ +import mock
│ │  
│ │  import pytest
│ │  
│ │ +from test import fails_on_travis_gce, requires_ssl_context_keyfile_password
│ │ +
│ │  
│ │  class TestCookies(SocketDummyServerTestCase):
│ │  
│ │      def test_multi_setcookie(self):
│ │          def multicookie_response_handler(listener):
│ │              sock = listener.accept()[0]
│ │  
│ │ @@ -225,14 +231,88 @@
│ │          else:
│ │              done_receiving.set()
│ │              self.fail(
│ │                  "Expected server to reject connection due to missing client "
│ │                  "certificates"
│ │              )
│ │  
│ │ +    @requires_ssl_context_keyfile_password
│ │ +    def test_client_cert_with_string_password(self):
│ │ +        self.run_client_cert_with_password_test(u"letmein")
│ │ +
│ │ +    @requires_ssl_context_keyfile_password
│ │ +    def test_client_cert_with_bytes_password(self):
│ │ +        self.run_client_cert_with_password_test(b"letmein")
│ │ +
│ │ +    def run_client_cert_with_password_test(self, password):
│ │ +        """
│ │ +        Tests client certificate password functionality
│ │ +        """
│ │ +        done_receiving = Event()
│ │ +        client_certs = []
│ │ +
│ │ +        def socket_handler(listener):
│ │ +            sock = listener.accept()[0]
│ │ +            sock = self._wrap_in_ssl(sock)
│ │ +
│ │ +            client_certs.append(sock.getpeercert())
│ │ +
│ │ +            data = b''
│ │ +            while not data.endswith(b'\r\n\r\n'):
│ │ +                data += sock.recv(8192)
│ │ +
│ │ +            sock.sendall(
│ │ +                b'HTTP/1.1 200 OK\r\n'
│ │ +                b'Server: testsocket\r\n'
│ │ +                b'Connection: close\r\n'
│ │ +                b'Content-Length: 6\r\n'
│ │ +                b'\r\n'
│ │ +                b'Valid!'
│ │ +            )
│ │ +
│ │ +            done_receiving.wait(5)
│ │ +            sock.close()
│ │ +
│ │ +        self._start_server(socket_handler)
│ │ +        ssl_context = ssl_.SSLContext(ssl_.PROTOCOL_SSLv23)
│ │ +        ssl_context.load_cert_chain(
│ │ +            certfile=DEFAULT_CERTS['certfile'],
│ │ +            keyfile=PASSWORD_KEYFILE,
│ │ +            password=password
│ │ +        )
│ │ +
│ │ +        pool = HTTPSConnectionPool(
│ │ +            self.host,
│ │ +            self.port,
│ │ +            ssl_context=ssl_context,
│ │ +            cert_reqs='REQUIRED',
│ │ +            ca_certs=DEFAULT_CA,
│ │ +        )
│ │ +        self.addCleanup(pool.close)
│ │ +        pool.request('GET', '/', retries=0)
│ │ +        done_receiving.set()
│ │ +
│ │ +        self.assertEqual(len(client_certs), 1)
│ │ +
│ │ +    @requires_ssl_context_keyfile_password
│ │ +    def test_load_keyfile_with_invalid_password(self):
│ │ +        context = ssl_.SSLContext(ssl_.PROTOCOL_SSLv23)
│ │ +
│ │ +        # Different error is raised depending on context.
│ │ +        if ssl_.IS_PYOPENSSL:
│ │ +            from OpenSSL.SSL import Error
│ │ +            expected_error = Error
│ │ +        else:
│ │ +            expected_error = ssl.SSLError
│ │ +
│ │ +        with pytest.raises(expected_error):
│ │ +            context.load_cert_chain(certfile=DEFAULT_CERTS["certfile"],
│ │ +                                    keyfile=PASSWORD_KEYFILE,
│ │ +                                    password=b'letmei')
│ │ +
│ │  
│ │  class TestSocketClosing(SocketDummyServerTestCase):
│ │  
│ │      def test_recovery_when_server_closes_connection(self):
│ │          # Does the pool work seamlessly if an open connection in the
│ │          # connection pool gets hung up on by the server, then reaches
│ │          # the front of the queue again?
│ │ @@ -288,15 +368,15 @@
│ │                  pass
│ │  
│ │              timed_out.wait()
│ │              sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │          http = HTTPConnectionPool(self.host, self.port,
│ │ -                                  timeout=0.001,
│ │ +                                  timeout=0.01,
│ │                                    retries=False,
│ │                                    maxsize=3,
│ │                                    block=True)
│ │          self.addCleanup(http.close)
│ │  
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, http.request, 'GET', '/', release_conn=False)
│ │ @@ -311,15 +391,15 @@
│ │          def socket_handler(listener):
│ │              sock = listener.accept()[0]
│ │              sock.recv(65536)
│ │              timed_out.wait()
│ │              sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │ -        pool = HTTPConnectionPool(self.host, self.port, timeout=0.001, retries=True)
│ │ +        pool = HTTPConnectionPool(self.host, self.port, timeout=0.01, retries=True)
│ │          self.addCleanup(pool.close)
│ │  
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, pool.request, 'POST', '/')
│ │          finally:
│ │              timed_out.set()
│ │  
│ │ @@ -332,15 +412,15 @@
│ │              while not sock.recv(65536):
│ │                  pass
│ │  
│ │              timed_out.wait()
│ │              sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │ -        pool = HTTPSConnectionPool(self.host, self.port, timeout=0.001, retries=False)
│ │ +        pool = HTTPSConnectionPool(self.host, self.port, timeout=0.01, retries=False)
│ │          self.addCleanup(pool.close)
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
│ │          finally:
│ │              timed_out.set()
│ │  
│ │      def test_timeout_errors_cause_retries(self):
│ │ @@ -371,15 +451,15 @@
│ │          # out within 1 second. This should be long enough for any socket
│ │          # operations in the test suite to complete
│ │          default_timeout = socket.getdefaulttimeout()
│ │          socket.setdefaulttimeout(1)
│ │  
│ │          try:
│ │              self._start_server(socket_handler)
│ │ -            t = Timeout(connect=0.001, read=0.001)
│ │ +            t = Timeout(connect=0.001, read=0.01)
│ │              pool = HTTPConnectionPool(self.host, self.port, timeout=t)
│ │              self.addCleanup(pool.close)
│ │  
│ │              response = pool.request('GET', '/', retries=1)
│ │              self.assertEqual(response.status, 200)
│ │              self.assertEqual(response.data, b'Response 2')
│ │          finally:
│ │ @@ -404,15 +484,15 @@
│ │              sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │          pool = HTTPConnectionPool(self.host, self.port)
│ │          self.addCleanup(pool.close)
│ │  
│ │          response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ -                                timeout=Timeout(connect=1, read=0.001))
│ │ +                                timeout=Timeout(connect=1, read=0.01))
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, response.read)
│ │          finally:
│ │              timed_out.set()
│ │  
│ │      def test_delayed_body_read_timeout_with_preload(self):
│ │          timed_out = Event()
│ │ @@ -434,15 +514,15 @@
│ │          self._start_server(socket_handler)
│ │          pool = HTTPConnectionPool(self.host, self.port)
│ │          self.addCleanup(pool.close)
│ │  
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, pool.urlopen,
│ │                                'GET', '/', retries=False,
│ │ -                              timeout=Timeout(connect=1, read=0.001))
│ │ +                              timeout=Timeout(connect=1, read=0.01))
│ │          finally:
│ │              timed_out.set()
│ │  
│ │      def test_incomplete_response(self):
│ │          body = 'Response'
│ │          partial_body = body[:2]
│ │  
│ │ @@ -531,15 +611,15 @@
│ │              timed_out.wait()
│ │              sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │          with HTTPConnectionPool(self.host, self.port) as pool:
│ │              poolsize = pool.pool.qsize()
│ │              response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ -                                    timeout=Timeout(connect=1, read=0.001))
│ │ +                                    timeout=Timeout(connect=1, read=0.01))
│ │              try:
│ │                  self.assertRaises(ReadTimeoutError, response.read)
│ │                  self.assertEqual(poolsize, pool.pool.qsize())
│ │              finally:
│ │                  timed_out.set()
│ │  
│ │      def test_connection_cleanup_on_protocol_error_during_read(self):
│ │ @@ -620,24 +700,24 @@
│ │              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))
│ │ +                                    timeout=Timeout(connect=1, read=0.1))
│ │              try:
│ │                  self.assertRaises(ReadTimeoutError, response.read)
│ │              finally:
│ │                  timed_out.set()
│ │  
│ │              # Second should succeed.
│ │              response = pool.urlopen('GET', '/', retries=0,
│ │                                      preload_content=False,
│ │ -                                    timeout=Timeout(connect=1, read=0.1))
│ │ +                                    timeout=Timeout(connect=1, read=1))
│ │              self.assertEqual(len(response.read()), 8)
│ │  
│ │      def test_closing_response_actually_closes_connection(self):
│ │          done_closing = Event()
│ │          complete = Event()
│ │  
│ │          def socket_handler(listener):
│ │ @@ -720,15 +800,15 @@
│ │  
│ │          self._start_server(socket_handler)
│ │          with HTTPConnectionPool(self.host, self.port, maxsize=1) as pool:
│ │              # First request should fail, but the timeout and `retries=1` should
│ │              # save it.
│ │              response = pool.urlopen('GET', '/', retries=1,
│ │                                      release_conn=False, preload_content=False,
│ │ -                                    timeout=Timeout(connect=1, read=0.001))
│ │ +                                    timeout=Timeout(connect=1, read=0.01))
│ │  
│ │              # The connection should still be on the response object, and none
│ │              # should be in the pool. We opened two though.
│ │              self.assertEqual(pool.num_connections, 2)
│ │              self.assertEqual(pool.pool.qsize(), 0)
│ │              self.assertIsNotNone(response.connection)
│ │  
│ │ @@ -889,15 +969,15 @@
│ │          def echo_socket_handler(listener):
│ │              proxy_ssl_one(listener)
│ │              proxy_ssl_one(listener)
│ │  
│ │          self._start_server(echo_socket_handler)
│ │          base_url = 'http://%s:%d' % (self.host, self.port)
│ │  
│ │ -        proxy = proxy_from_url(base_url)
│ │ +        proxy = proxy_from_url(base_url, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(proxy.clear)
│ │  
│ │          url = 'https://{0}'.format(self.host)
│ │          conn = proxy.connection_from_url(url)
│ │          r = conn.urlopen('GET', url, retries=0)
│ │          self.assertEqual(r.status, 200)
│ │          r = conn.urlopen('GET', url, retries=0)
│ │ @@ -933,15 +1013,15 @@
│ │                  ssl_sock.close()
│ │              else:
│ │                  sock.close()
│ │  
│ │          self._start_server(echo_socket_handler)
│ │          base_url = 'http://%s:%d' % (self.host, self.port)
│ │  
│ │ -        proxy = proxy_from_url(base_url)
│ │ +        proxy = proxy_from_url(base_url, cert_reqs='NONE')
│ │          self.addCleanup(proxy.clear)
│ │  
│ │          url = 'https://[{0}]'.format(ipv6_addr)
│ │          conn = proxy.connection_from_url(url)
│ │          try:
│ │              r = conn.urlopen('GET', url, retries=0)
│ │              self.assertEqual(r.status, 200)
│ │ @@ -987,16 +1067,15 @@
│ │          timed_out = Event()
│ │  
│ │          def socket_handler(listener):
│ │              sock = listener.accept()[0]
│ │              ssl_sock = ssl.wrap_socket(sock,
│ │                                         server_side=True,
│ │                                         keyfile=DEFAULT_CERTS['keyfile'],
│ │ -                                       certfile=DEFAULT_CERTS['certfile'],
│ │ -                                       ca_certs=DEFAULT_CA)
│ │ +                                       certfile=DEFAULT_CERTS['certfile'])
│ │  
│ │              buf = b''
│ │              while not buf.endswith(b'\r\n\r\n'):
│ │                  buf += ssl_sock.recv(65536)
│ │  
│ │              # Send incomplete message (note Content-Length)
│ │              ssl_sock.send((
│ │ @@ -1007,19 +1086,19 @@
│ │                  'Hi-').encode('utf-8'))
│ │              timed_out.wait()
│ │  
│ │              sock.close()
│ │              ssl_sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │ -        pool = HTTPSConnectionPool(self.host, self.port)
│ │ +        pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(pool.close)
│ │  
│ │          response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ -                                timeout=Timeout(connect=1, read=0.001))
│ │ +                                timeout=Timeout(connect=1, read=0.01))
│ │          try:
│ │              self.assertRaises(ReadTimeoutError, response.read)
│ │          finally:
│ │              timed_out.set()
│ │  
│ │      def test_ssl_failed_fingerprint_verification(self):
│ │          def socket_handler(listener):
│ │ @@ -1045,15 +1124,15 @@
│ │                         ':9A:8C:B6:07:CA:58:EE:74:5E')
│ │  
│ │          def request():
│ │              pool = HTTPSConnectionPool(self.host, self.port,
│ │                                         assert_fingerprint=fingerprint)
│ │              try:
│ │                  response = pool.urlopen('GET', '/', preload_content=False,
│ │ -                                        timeout=Timeout(connect=1, read=0.001),
│ │ +                                        timeout=Timeout(connect=1, read=0.01),
│ │                                          retries=0)
│ │                  response.read()
│ │              finally:
│ │                  pool.close()
│ │  
│ │          with self.assertRaises(MaxRetryError) as cm:
│ │              request()
│ │ @@ -1097,19 +1176,96 @@
│ │                            b'Content-Type: text/plain\r\n'
│ │                            b'Content-Length: 7\r\n\r\n'
│ │                            b'Success')
│ │              ssl_sock.close()
│ │  
│ │          self._start_server(socket_handler)
│ │  
│ │ -        pool = HTTPSConnectionPool(self.host, self.port)
│ │ +        pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(pool.close)
│ │          response = pool.urlopen('GET', '/', retries=1)
│ │          self.assertEqual(response.data, b'Success')
│ │  
│ │ +    def test_ssl_load_default_certs_when_empty(self):
│ │ +        def socket_handler(listener):
│ │ +            sock = listener.accept()[0]
│ │ +            ssl_sock = ssl.wrap_socket(sock,
│ │ +                                       server_side=True,
│ │ +                                       keyfile=DEFAULT_CERTS['keyfile'],
│ │ +                                       certfile=DEFAULT_CERTS['certfile'],
│ │ +                                       ca_certs=DEFAULT_CA)
│ │ +
│ │ +            buf = b''
│ │ +            while not buf.endswith(b'\r\n\r\n'):
│ │ +                buf += ssl_sock.recv(65536)
│ │ +
│ │ +            ssl_sock.send(b'HTTP/1.1 200 OK\r\n'
│ │ +                          b'Content-Type: text/plain\r\n'
│ │ +                          b'Content-Length: 5\r\n\r\n'
│ │ +                          b'Hello')
│ │ +
│ │ +            ssl_sock.close()
│ │ +            sock.close()
│ │ +
│ │ +        context = mock.create_autospec(ssl_.SSLContext)
│ │ +        context.load_default_certs = mock.Mock()
│ │ +        context.options = 0
│ │ +
│ │ +        with mock.patch("urllib3.util.ssl_.SSLContext", lambda *_, **__: context):
│ │ +
│ │ +            self._start_server(socket_handler)
│ │ +            pool = HTTPSConnectionPool(self.host, self.port)
│ │ +            self.addCleanup(pool.close)
│ │ +
│ │ +            with self.assertRaises(MaxRetryError):
│ │ +                pool.request("GET", "/", timeout=0.01)
│ │ +
│ │ +            context.load_default_certs.assert_called_with()
│ │ +
│ │ +    def test_ssl_dont_load_default_certs_when_given(self):
│ │ +        def socket_handler(listener):
│ │ +            sock = listener.accept()[0]
│ │ +            ssl_sock = ssl.wrap_socket(sock,
│ │ +                                       server_side=True,
│ │ +                                       keyfile=DEFAULT_CERTS['keyfile'],
│ │ +                                       certfile=DEFAULT_CERTS['certfile'],
│ │ +                                       ca_certs=DEFAULT_CA)
│ │ +
│ │ +            buf = b''
│ │ +            while not buf.endswith(b'\r\n\r\n'):
│ │ +                buf += ssl_sock.recv(65536)
│ │ +
│ │ +            ssl_sock.send(b'HTTP/1.1 200 OK\r\n'
│ │ +                          b'Content-Type: text/plain\r\n'
│ │ +                          b'Content-Length: 5\r\n\r\n'
│ │ +                          b'Hello')
│ │ +
│ │ +            ssl_sock.close()
│ │ +            sock.close()
│ │ +
│ │ +        context = mock.create_autospec(ssl_.SSLContext)
│ │ +        context.load_default_certs = mock.Mock()
│ │ +        context.options = 0
│ │ +
│ │ +        with mock.patch("urllib3.util.ssl_.SSLContext", lambda *_, **__: context):
│ │ +            for kwargs in [{"ca_certs": "/a"},
│ │ +                           {"ca_cert_dir": "/a"},
│ │ +                           {"ca_certs": "a", "ca_cert_dir": "a"},
│ │ +                           {"ssl_context": context}]:
│ │ +
│ │ +                self._start_server(socket_handler)
│ │ +
│ │ +                pool = HTTPSConnectionPool(self.host, self.port, **kwargs)
│ │ +                self.addCleanup(pool.close)
│ │ +
│ │ +                with self.assertRaises(MaxRetryError):
│ │ +                    pool.request("GET", "/", timeout=0.01)
│ │ +
│ │ +                context.load_default_certs.assert_not_called()
│ │ +
│ │  
│ │  class TestErrorWrapping(SocketDummyServerTestCase):
│ │  
│ │      def test_bad_statusline(self):
│ │          self.start_response_handler(
│ │             b'HTTP/1.1 Omg What Is This?\r\n'
│ │             b'Content-Length: 0\r\n'
│ │ @@ -1214,14 +1370,15 @@
│ │          self._start_server(socket_handler)
│ │  
│ │          pool = HTTPConnectionPool(self.host, self.port, retries=False)
│ │          self.addCleanup(pool.close)
│ │          pool.request('GET', '/', headers=OrderedDict(expected_request_headers))
│ │          self.assertEqual(expected_request_headers, actual_request_headers)
│ │  
│ │ +    @fails_on_travis_gce
│ │      def test_request_host_header_ignores_fqdn_dot(self):
│ │  
│ │          received_headers = []
│ │  
│ │          def socket_handler(listener):
│ │              sock = listener.accept()[0]
│   --- urllib3-1.24.1/test/test_response.py
├── +++ urllib3-1.25.3/test/test_response.py
│┄ Files similar despite different names (difference score: 4)
│ │ @@ -2,22 +2,24 @@
│ │  import zlib
│ │  
│ │  from io import BytesIO, BufferedReader
│ │  
│ │  import pytest
│ │  import mock
│ │  
│ │ -from urllib3.response import HTTPResponse
│ │ +from urllib3.response import HTTPResponse, brotli
│ │  from urllib3.exceptions import (
│ │      DecodeError, ResponseNotChunked, ProtocolError, InvalidHeader
│ │  )
│ │  from urllib3.packages.six.moves import http_client as httplib
│ │  from urllib3.util.retry import Retry, RequestHistory
│ │  from urllib3.util.response import is_fp_closed
│ │  
│ │ +from test import onlyBrotlipy
│ │ +
│ │  from base64 import b64decode
│ │  
│ │  # A known random (i.e, not-too-compressible) payload generated with:
│ │  #    "".join(random.choice(string.printable) for i in xrange(512))
│ │  #    .encode("zlib").encode("base64")
│ │  # Randomness in tests == bad, and fixing a seed may not be sufficient.
│ │  ZLIB_PAYLOAD = b64decode(b"""\
│ │ @@ -204,14 +206,43 @@
│ │          data = data * 3 + b'foo'
│ │  
│ │          fp = BytesIO(data)
│ │          r = HTTPResponse(fp, headers={'content-encoding': 'gzip'})
│ │  
│ │          assert r.data == b'foofoofoo'
│ │  
│ │ +    @onlyBrotlipy()
│ │ +    def test_decode_brotli(self):
│ │ +        data = brotli.compress(b'foo')
│ │ +
│ │ +        fp = BytesIO(data)
│ │ +        r = HTTPResponse(fp, headers={'content-encoding': 'br'})
│ │ +        assert r.data == b'foo'
│ │ +
│ │ +    @onlyBrotlipy()
│ │ +    def test_chunked_decoding_brotli(self):
│ │ +        data = brotli.compress(b'foobarbaz')
│ │ +
│ │ +        fp = BytesIO(data)
│ │ +        r = HTTPResponse(
│ │ +            fp, headers={'content-encoding': 'br'}, preload_content=False)
│ │ +
│ │ +        ret = b''
│ │ +        for _ in range(100):
│ │ +            ret += r.read(1)
│ │ +            if r.closed:
│ │ +                break
│ │ +        assert ret == b'foobarbaz'
│ │ +
│ │ +    @onlyBrotlipy()
│ │ +    def test_decode_brotli_error(self):
│ │ +        fp = BytesIO(b'foo')
│ │ +        with pytest.raises(DecodeError):
│ │ +            HTTPResponse(fp, headers={'content-encoding': 'br'})
│ │ +
│ │      def test_multi_decoding_deflate_deflate(self):
│ │          data = zlib.compress(zlib.compress(b'foo'))
│ │  
│ │          fp = BytesIO(data)
│ │          r = HTTPResponse(fp, headers={'content-encoding': 'deflate, deflate'})
│ │  
│ │          assert r.data == b'foo'
│ │ @@ -704,14 +735,49 @@
│ │                             status=301, redirect_location='https://example.com/'),
│ │              RequestHistory(method='GET', url='https://example.com/', error=None,
│ │                             status=301, redirect_location='https://www.example.com')]
│ │          retry = Retry(history=request_histories)
│ │          resp = HTTPResponse(fp, retries=retry)
│ │          assert resp.geturl() == 'https://www.example.com'
│ │  
│ │ +    @pytest.mark.parametrize(
│ │ +        ["payload", "expected_stream"],
│ │ +        [(b"", [b""]),
│ │ +         (b"\n", [b"\n"]),
│ │ +         (b"abc\ndef", [b"abc\n", b"def"]),
│ │ +         (b"Hello\nworld\n\n\n!", [b"Hello\n", b"world\n", b"\n", b"\n", b"!"])]
│ │ +    )
│ │ +    def test__iter__(self, payload, expected_stream):
│ │ +        actual_stream = []
│ │ +        for chunk in HTTPResponse(BytesIO(payload), preload_content=False):
│ │ +            actual_stream.append(chunk)
│ │ +
│ │ +        assert actual_stream == expected_stream
│ │ +
│ │ +    def test__iter__decode_content(self):
│ │ +        def stream():
│ │ +            # Set up a generator to chunk the gzipped body
│ │ +            compress = zlib.compressobj(6, zlib.DEFLATED, 16 + zlib.MAX_WBITS)
│ │ +            data = compress.compress(b'foo\nbar')
│ │ +            data += compress.flush()
│ │ +            for i in range(0, len(data), 2):
│ │ +                yield data[i:i + 2]
│ │ +
│ │ +        fp = MockChunkedEncodingResponse(list(stream()))
│ │ +        r = httplib.HTTPResponse(MockSock)
│ │ +        r.fp = fp
│ │ +        headers = {'transfer-encoding': 'chunked', 'content-encoding': 'gzip'}
│ │ +        resp = HTTPResponse(r, preload_content=False, headers=headers)
│ │ +
│ │ +        data = b''
│ │ +        for c in resp:
│ │ +            data += c
│ │ +
│ │ +        assert b'foo\nbar' == data
│ │ +
│ │  
│ │  class MockChunkedEncodingResponse(object):
│ │  
│ │      def __init__(self, content):
│ │          """
│ │          content: collection of str, each str is a chunk in response
│ │          """
│   --- urllib3-1.24.1/docs/conf.py
├── +++ urllib3-1.25.3/docs/conf.py
│┄ Files similar despite different names (difference score: 4)
│ │ @@ -130,15 +130,15 @@
│ │  html_theme = 'alabaster'
│ │  
│ │  # Theme options are theme-specific and customize the look and feel of a theme
│ │  # further.  For a list of options available for each theme, see the
│ │  # documentation.
│ │  html_theme_options = {
│ │      'description': 'Sanity-friendly HTTP client.',
│ │ -    'github_user': 'shazow',
│ │ +    'github_user': 'urllib3',
│ │      'github_repo': 'urllib3',
│ │      'github_button': False,
│ │      'github_banner': True,
│ │      'travis_button': True,
│ │      'show_powered_by': False,
│ │      'font_family': "'Roboto', Georgia, sans",
│ │      'head_font_family': "'Roboto', Georgia, serif",
│ │ @@ -267,8 +267,8 @@
│ │  # (source start file, name, description, authors, manual section).
│ │  man_pages = [
│ │      ('index', 'urllib3', u'urllib3 Documentation',
│ │       [u'Andrey Petrov'], 1)
│ │  ]
│ │  
│ │  intersphinx_mapping = {
│ │ -    'python': ('https://docs.python.org/3.5', None),}
│ │ +    'python': ('https://docs.python.org/3.7', None),}
│   --- urllib3-1.24.1/dummyserver/certs/server.key
├── +++ urllib3-1.25.3/dummyserver/certs/server.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/connectionpool.py
├── +++ urllib3-1.25.3/src/urllib3/connectionpool.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -22,14 +22,15 @@
│ │      TimeoutError,
│ │      InsecureRequestWarning,
│ │      NewConnectionError,
│ │  )
│ │  from .packages.ssl_match_hostname import CertificateError
│ │  from .packages import six
│ │  from .packages.six.moves import queue
│ │ +from .packages.rfc3986.normalizers import normalize_host
│ │  from .connection import (
│ │      port_by_scheme,
│ │      DummyConnection,
│ │      HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection,
│ │      HTTPException, BaseSSLError,
│ │  )
│ │  from .request import RequestMethods
│ │ @@ -61,15 +62,15 @@
│ │      scheme = None
│ │      QueueCls = LifoQueue
│ │  
│ │      def __init__(self, host, port=None):
│ │          if not host:
│ │              raise LocationValueError("No host specified.")
│ │  
│ │ -        self.host = _ipv6_host(host, self.scheme)
│ │ +        self.host = _normalize_host(host, scheme=self.scheme)
│ │          self._proxy_host = host.lower()
│ │          self.port = port
│ │  
│ │      def __str__(self):
│ │          return '%s(host=%r, port=%r)' % (type(self).__name__,
│ │                                           self.host, self.port)
│ │  
│ │ @@ -369,17 +370,19 @@
│ │              if read_timeout is Timeout.DEFAULT_TIMEOUT:
│ │                  conn.sock.settimeout(socket.getdefaulttimeout())
│ │              else:  # None or a value
│ │                  conn.sock.settimeout(read_timeout)
│ │  
│ │          # Receive the response from the server
│ │          try:
│ │ -            try:  # Python 2.7, use buffering of HTTP responses
│ │ +            try:
│ │ +                # Python 2.7, use buffering of HTTP responses
│ │                  httplib_response = conn.getresponse(buffering=True)
│ │ -            except TypeError:  # Python 3
│ │ +            except TypeError:
│ │ +                # Python 3
│ │                  try:
│ │                      httplib_response = conn.getresponse()
│ │                  except Exception as e:
│ │                      # Remove the TypeError from the exception chain in Python 3;
│ │                      # otherwise it looks like a programming error was the cause.
│ │                      six.raise_from(e, None)
│ │          except (SocketTimeout, BaseSSLError, SocketError) as e:
│ │ @@ -428,16 +431,16 @@
│ │          connection pool.
│ │          """
│ │          if url.startswith('/'):
│ │              return True
│ │  
│ │          # TODO: Add optional support for socket.gethostbyname checking.
│ │          scheme, host, port = get_host(url)
│ │ -
│ │ -        host = _ipv6_host(host, self.scheme)
│ │ +        if host is not None:
│ │ +            host = _normalize_host(host, scheme=scheme)
│ │  
│ │          # Use explicit default port for comparison when none is given
│ │          if self.port and not port:
│ │              port = port_by_scheme.get(scheme)
│ │          elif not self.port and port == port_by_scheme.get(scheme):
│ │              port = None
│ │  
│ │ @@ -668,15 +671,15 @@
│ │  
│ │          def drain_and_release_conn(response):
│ │              try:
│ │                  # discard any remaining response body, the connection will be
│ │                  # released back to the pool once the entire response is read
│ │                  response.read()
│ │              except (TimeoutError, HTTPException, SocketError, ProtocolError,
│ │ -                    BaseSSLError, SSLError) as e:
│ │ +                    BaseSSLError, SSLError):
│ │                  pass
│ │  
│ │          # Handle redirect?
│ │          redirect_location = redirect and response.get_redirect_location()
│ │          if redirect_location:
│ │              if response.status == 303:
│ │                  method = 'GET'
│ │ @@ -742,55 +745,54 @@
│ │      instead of :class:`.HTTPSConnection`.
│ │  
│ │      :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``,
│ │      ``assert_hostname`` and ``host`` in this order to verify connections.
│ │      If ``assert_hostname`` is False, no verification is done.
│ │  
│ │      The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``,
│ │ -    ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is
│ │ -    available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade
│ │ +    ``ca_cert_dir``, ``ssl_version``, ``key_password`` are only used if :mod:`ssl`
│ │ +    is available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade
│ │      the connection socket into an SSL socket.
│ │      """
│ │  
│ │      scheme = 'https'
│ │      ConnectionCls = HTTPSConnection
│ │  
│ │      def __init__(self, host, port=None,
│ │                   strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1,
│ │                   block=False, headers=None, retries=None,
│ │                   _proxy=None, _proxy_headers=None,
│ │                   key_file=None, cert_file=None, cert_reqs=None,
│ │ -                 ca_certs=None, ssl_version=None,
│ │ +                 key_password=None, ca_certs=None, ssl_version=None,
│ │                   assert_hostname=None, assert_fingerprint=None,
│ │                   ca_cert_dir=None, **conn_kw):
│ │  
│ │          HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize,
│ │                                      block, headers, retries, _proxy, _proxy_headers,
│ │                                      **conn_kw)
│ │  
│ │ -        if ca_certs and cert_reqs is None:
│ │ -            cert_reqs = 'CERT_REQUIRED'
│ │ -
│ │          self.key_file = key_file
│ │          self.cert_file = cert_file
│ │          self.cert_reqs = cert_reqs
│ │ +        self.key_password = key_password
│ │          self.ca_certs = ca_certs
│ │          self.ca_cert_dir = ca_cert_dir
│ │          self.ssl_version = ssl_version
│ │          self.assert_hostname = assert_hostname
│ │          self.assert_fingerprint = assert_fingerprint
│ │  
│ │      def _prepare_conn(self, conn):
│ │          """
│ │          Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket`
│ │          and establish the tunnel if proxy is used.
│ │          """
│ │  
│ │          if isinstance(conn, VerifiedHTTPSConnection):
│ │              conn.set_cert(key_file=self.key_file,
│ │ +                          key_password=self.key_password,
│ │                            cert_file=self.cert_file,
│ │                            cert_reqs=self.cert_reqs,
│ │                            ca_certs=self.ca_certs,
│ │                            ca_cert_dir=self.ca_cert_dir,
│ │                            assert_hostname=self.assert_hostname,
│ │                            assert_fingerprint=self.assert_fingerprint)
│ │              conn.ssl_version = self.ssl_version
│ │ @@ -820,15 +822,17 @@
│ │          actual_port = self.port
│ │          if self.proxy is not None:
│ │              actual_host = self.proxy.host
│ │              actual_port = self.proxy.port
│ │  
│ │          conn = self.ConnectionCls(host=actual_host, port=actual_port,
│ │                                    timeout=self.timeout.connect_timeout,
│ │ -                                  strict=self.strict, **self.conn_kw)
│ │ +                                  strict=self.strict, cert_file=self.cert_file,
│ │ +                                  key_file=self.key_file, key_password=self.key_password,
│ │ +                                  **self.conn_kw)
│ │  
│ │          return self._prepare_conn(conn)
│ │  
│ │      def _validate_conn(self, conn):
│ │          """
│ │          Called right before a request is made, after the socket is created.
│ │          """
│ │ @@ -871,26 +875,23 @@
│ │      port = port or port_by_scheme.get(scheme, 80)
│ │      if scheme == 'https':
│ │          return HTTPSConnectionPool(host, port=port, **kw)
│ │      else:
│ │          return HTTPConnectionPool(host, port=port, **kw)
│ │  
│ │  
│ │ -def _ipv6_host(host, scheme):
│ │ +def _normalize_host(host, scheme):
│ │      """
│ │ -    Process IPv6 address literals
│ │ +    Normalize hosts for comparisons and use with sockets.
│ │      """
│ │  
│ │      # httplib doesn't like it when we include brackets in IPv6 addresses
│ │      # Specifically, if we include brackets but also pass the port then
│ │      # httplib crazily doubles up the square brackets on the Host header.
│ │      # Instead, we need to make sure we never pass ``None`` as the port.
│ │      # However, for backward compatibility reasons we can't actually
│ │      # *assert* that.  See http://bugs.python.org/issue28539
│ │ -    #
│ │ -    # Also if an IPv6 address literal has a zone identifier, the
│ │ -    # percent sign might be URIencoded, convert it back into ASCII
│ │      if host.startswith('[') and host.endswith(']'):
│ │ -        host = host.replace('%25', '%').strip('[]')
│ │ +        host = host.strip('[]')
│ │      if scheme in NORMALIZABLE_SCHEMES:
│ │ -        host = host.lower()
│ │ +        host = normalize_host(host)
│ │      return host
│   --- urllib3-1.24.1/src/urllib3/contrib/pyopenssl.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/pyopenssl.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -66,35 +66,35 @@
│ │  import logging
│ │  import ssl
│ │  from ..packages import six
│ │  import sys
│ │  
│ │  from .. import util
│ │  
│ │ +
│ │  __all__ = ['inject_into_urllib3', 'extract_from_urllib3']
│ │  
│ │  # SNI always works.
│ │  HAS_SNI = True
│ │  
│ │  # Map from urllib3 to PyOpenSSL compatible parameter-values.
│ │  _openssl_versions = {
│ │ -    ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD,
│ │ +    util.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD,
│ │      ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
│ │  }
│ │  
│ │ +if hasattr(ssl, 'PROTOCOL_SSLv3') and hasattr(OpenSSL.SSL, 'SSLv3_METHOD'):
│ │ +    _openssl_versions[ssl.PROTOCOL_SSLv3] = OpenSSL.SSL.SSLv3_METHOD
│ │ +
│ │  if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'):
│ │      _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD
│ │  
│ │  if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
│ │      _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD
│ │  
│ │ -try:
│ │ -    _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD})
│ │ -except AttributeError:
│ │ -    pass
│ │  
│ │  _stdlib_to_openssl_verify = {
│ │      ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE,
│ │      ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER,
│ │      ssl.CERT_REQUIRED:
│ │          OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
│ │  }
│ │ @@ -113,24 +113,26 @@
│ │  
│ │  
│ │  def inject_into_urllib3():
│ │      'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.'
│ │  
│ │      _validate_dependencies_met()
│ │  
│ │ +    util.SSLContext = PyOpenSSLContext
│ │      util.ssl_.SSLContext = PyOpenSSLContext
│ │      util.HAS_SNI = HAS_SNI
│ │      util.ssl_.HAS_SNI = HAS_SNI
│ │      util.IS_PYOPENSSL = True
│ │      util.ssl_.IS_PYOPENSSL = True
│ │  
│ │  
│ │  def extract_from_urllib3():
│ │      'Undo monkey-patching by :func:`inject_into_urllib3`.'
│ │  
│ │ +    util.SSLContext = orig_util_SSLContext
│ │      util.ssl_.SSLContext = orig_util_SSLContext
│ │      util.HAS_SNI = orig_util_HAS_SNI
│ │      util.ssl_.HAS_SNI = orig_util_HAS_SNI
│ │      util.IS_PYOPENSSL = False
│ │      util.ssl_.IS_PYOPENSSL = False
│ │  
│ │  
│ │ @@ -180,14 +182,18 @@
│ │                  if name.startswith(prefix):
│ │                      name = name[len(prefix):]
│ │                      return prefix.encode('ascii') + idna.encode(name)
│ │              return idna.encode(name)
│ │          except idna.core.IDNAError:
│ │              return None
│ │  
│ │ +    # Don't send IPv6 addresses through the IDNA encoder.
│ │ +    if ':' in name:
│ │ +        return name
│ │ +
│ │      name = idna_encode(name)
│ │      if name is None:
│ │          return None
│ │      elif sys.version_info >= (3, 0):
│ │          name = name.decode('utf-8')
│ │      return name
│ │  
│ │ @@ -272,46 +278,54 @@
│ │          try:
│ │              data = self.connection.recv(*args, **kwargs)
│ │          except OpenSSL.SSL.SysCallError as e:
│ │              if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
│ │                  return b''
│ │              else:
│ │                  raise SocketError(str(e))
│ │ -        except OpenSSL.SSL.ZeroReturnError as e:
│ │ +        except OpenSSL.SSL.ZeroReturnError:
│ │              if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
│ │                  return b''
│ │              else:
│ │                  raise
│ │          except OpenSSL.SSL.WantReadError:
│ │              if not util.wait_for_read(self.socket, self.socket.gettimeout()):
│ │                  raise timeout('The read operation timed out')
│ │              else:
│ │                  return self.recv(*args, **kwargs)
│ │ +
│ │ +        # TLS 1.3 post-handshake authentication
│ │ +        except OpenSSL.SSL.Error as e:
│ │ +            raise ssl.SSLError("read error: %r" % e)
│ │          else:
│ │              return data
│ │  
│ │      def recv_into(self, *args, **kwargs):
│ │          try:
│ │              return self.connection.recv_into(*args, **kwargs)
│ │          except OpenSSL.SSL.SysCallError as e:
│ │              if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
│ │                  return 0
│ │              else:
│ │                  raise SocketError(str(e))
│ │ -        except OpenSSL.SSL.ZeroReturnError as e:
│ │ +        except OpenSSL.SSL.ZeroReturnError:
│ │              if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
│ │                  return 0
│ │              else:
│ │                  raise
│ │          except OpenSSL.SSL.WantReadError:
│ │              if not util.wait_for_read(self.socket, self.socket.gettimeout()):
│ │                  raise timeout('The read operation timed out')
│ │              else:
│ │                  return self.recv_into(*args, **kwargs)
│ │  
│ │ +        # TLS 1.3 post-handshake authentication
│ │ +        except OpenSSL.SSL.Error as e:
│ │ +            raise ssl.SSLError("read error: %r" % e)
│ │ +
│ │      def settimeout(self, timeout):
│ │          return self.socket.settimeout(timeout)
│ │  
│ │      def _send_until_done(self, data):
│ │          while True:
│ │              try:
│ │                  return self.connection.send(data)
│ │ @@ -356,14 +370,17 @@
│ │          return {
│ │              'subject': (
│ │                  (('commonName', x509.get_subject().CN),),
│ │              ),
│ │              'subjectAltName': get_subj_alt_name(x509)
│ │          }
│ │  
│ │ +    def version(self):
│ │ +        return self.connection.get_protocol_version_name()
│ │ +
│ │      def _reuse(self):
│ │          self._makefile_refs += 1
│ │  
│ │      def _drop(self):
│ │          if self._makefile_refs < 1:
│ │              self.close()
│ │          else:
│ │ @@ -428,15 +445,17 @@
│ │          self._ctx.load_verify_locations(cafile, capath)
│ │          if cadata is not None:
│ │              self._ctx.load_verify_locations(BytesIO(cadata))
│ │  
│ │      def load_cert_chain(self, certfile, keyfile=None, password=None):
│ │          self._ctx.use_certificate_chain_file(certfile)
│ │          if password is not None:
│ │ -            self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password)
│ │ +            if not isinstance(password, six.binary_type):
│ │ +                password = password.encode('utf-8')
│ │ +            self._ctx.set_passwd_cb(lambda *_: password)
│ │          self._ctx.use_privatekey_file(keyfile or certfile)
│ │  
│ │      def wrap_socket(self, sock, server_side=False,
│ │                      do_handshake_on_connect=True, suppress_ragged_eofs=True,
│ │                      server_hostname=None):
│ │          cnx = OpenSSL.SSL.Connection(self._ctx, sock)
│   --- urllib3-1.24.1/test/test_exceptions.py
├── +++ urllib3-1.25.3/test/test_exceptions.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3.egg-info/SOURCES.txt
├── +++ urllib3-1.25.3/src/urllib3.egg-info/SOURCES.txt
│┄ Files similar despite different names (difference score: 49)
│ │ @@ -31,26 +31,29 @@
│ │  dummyserver/certs/client.csr
│ │  dummyserver/certs/client.key
│ │  dummyserver/certs/client.pem
│ │  dummyserver/certs/client_bad.pem
│ │  dummyserver/certs/client_intermediate.key
│ │  dummyserver/certs/client_intermediate.pem
│ │  dummyserver/certs/client_no_intermediate.pem
│ │ +dummyserver/certs/client_password.key
│ │  dummyserver/certs/intermediate.key
│ │  dummyserver/certs/intermediate.pem
│ │  dummyserver/certs/server.combined.pem
│ │  dummyserver/certs/server.crt
│ │  dummyserver/certs/server.csr
│ │  dummyserver/certs/server.ip_san.crt
│ │ +dummyserver/certs/server.ipv6_san.crt
│ │  dummyserver/certs/server.ipv6addr.crt
│ │  dummyserver/certs/server.ipv6addr.key
│ │  dummyserver/certs/server.key
│ │  dummyserver/certs/server.key.org
│ │  dummyserver/certs/server.no_san.crt
│ │  dummyserver/certs/server.no_san.csr
│ │ +dummyserver/certs/server_password.key
│ │  dummyserver/certs/ca_path_test/98a2772e.0
│ │  dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │  dummyserver/certs/ca_path_test/cacert.pem
│ │  src/urllib3/__init__.py
│ │  src/urllib3/_collections.py
│ │  src/urllib3/connection.py
│ │  src/urllib3/connectionpool.py
│ │ @@ -75,14 +78,27 @@
│ │  src/urllib3/contrib/_securetransport/__init__.py
│ │  src/urllib3/contrib/_securetransport/bindings.py
│ │  src/urllib3/contrib/_securetransport/low_level.py
│ │  src/urllib3/packages/__init__.py
│ │  src/urllib3/packages/six.py
│ │  src/urllib3/packages/backports/__init__.py
│ │  src/urllib3/packages/backports/makefile.py
│ │ +src/urllib3/packages/rfc3986/__init__.py
│ │ +src/urllib3/packages/rfc3986/_mixin.py
│ │ +src/urllib3/packages/rfc3986/abnf_regexp.py
│ │ +src/urllib3/packages/rfc3986/api.py
│ │ +src/urllib3/packages/rfc3986/builder.py
│ │ +src/urllib3/packages/rfc3986/compat.py
│ │ +src/urllib3/packages/rfc3986/exceptions.py
│ │ +src/urllib3/packages/rfc3986/iri.py
│ │ +src/urllib3/packages/rfc3986/misc.py
│ │ +src/urllib3/packages/rfc3986/normalizers.py
│ │ +src/urllib3/packages/rfc3986/parseresult.py
│ │ +src/urllib3/packages/rfc3986/uri.py
│ │ +src/urllib3/packages/rfc3986/validators.py
│ │  src/urllib3/packages/ssl_match_hostname/__init__.py
│ │  src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │  src/urllib3/util/__init__.py
│ │  src/urllib3/util/connection.py
│ │  src/urllib3/util/queue.py
│ │  src/urllib3/util/request.py
│ │  src/urllib3/util/response.py
│   --- urllib3-1.24.1/test/test_compatibility.py
├── +++ urllib3-1.25.3/test/test_compatibility.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/README.rst
├── +++ urllib3-1.25.3/dummyserver/certs/README.rst
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client.key
├── +++ urllib3-1.25.3/dummyserver/certs/client.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/__init__.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.ipv6addr.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.ipv6addr.crt
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.crt
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/benchmark.py
├── +++ urllib3-1.25.3/test/benchmark.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client_intermediate.key
├── +++ urllib3-1.25.3/dummyserver/certs/client_intermediate.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.combined.pem
├── +++ urllib3-1.25.3/dummyserver/certs/server.combined.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/appengine/test_gae_manager.py
├── +++ urllib3-1.25.3/test/appengine/test_gae_manager.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/CHANGES.rst
├── +++ urllib3-1.25.3/CHANGES.rst
│┄ Files similar despite different names (difference score: 17)
│ │ @@ -1,16 +1,86 @@
│ │  Changes
│ │  =======
│ │  
│ │ +1.25.3 (2019-05-23)
│ │ +-------------------
│ │ +
│ │ +* Change ``HTTPSConnection`` to load system CA certificates
│ │ +  when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ +  unspecified. (Pull #1608, Issue #1603)
│ │ +
│ │ +* Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +
│ │ +
│ │ +1.25.2 (2019-04-28)
│ │ +-------------------
│ │ +
│ │ +* Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +
│ │ +* Change ``parse_url`` to percent-encode invalid characters within the
│ │ +  path, query, and target components. (Pull #1586)
│ │ +
│ │ +
│ │ +1.25.1 (2019-04-24)
│ │ +-------------------
│ │ +
│ │ +* Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +
│ │ +* Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +
│ │ +
│ │ +1.25 (2019-04-22)
│ │ +-----------------
│ │ +
│ │ +* Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +
│ │ +* Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +
│ │ +* Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ +  encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +
│ │ +* Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ +  implementations. (Pull #1496)
│ │ +
│ │ +* Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +
│ │ +* Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ +  given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +
│ │ +* Added support for Brotli content encoding. It is enabled automatically if
│ │ +  ``brotlipy`` package is installed which can be requested with
│ │ +  ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +
│ │ +* Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ +  Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +
│ │ +* Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +
│ │ +1.24.3 (2019-05-01)
│ │ +-------------------
│ │ +
│ │ +* Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +
│ │ +1.24.2 (2019-04-17)
│ │ +-------------------
│ │ +
│ │ +* Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ +  ``ssl_context`` parameters are specified.
│ │ +
│ │ +* Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +
│ │ +* Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +
│ │ +
│ │  1.24.1 (2018-11-02)
│ │  -------------------
│ │  
│ │  * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │  
│ │ -* Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ +* Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │  
│ │  
│ │  1.24 (2018-10-16)
│ │  -----------------
│ │  
│ │  * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│   --- urllib3-1.24.1/dummyserver/certs/ca_path_test/98a2772e.0
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/98a2772e.0
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/reference/urllib3.contrib.rst
├── +++ urllib3-1.25.3/docs/reference/urllib3.contrib.rst
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.ipv6addr.key
├── +++ urllib3-1.25.3/dummyserver/certs/server.ipv6addr.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/contrib/_appengine_environ.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_appengine_environ.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/__init__.py
│┄ Files similar despite different names (difference score: 6)
│ │ @@ -1,11 +1,10 @@
│ │  """
│ │  urllib3 - Thread-safe connection pooling and re-using.
│ │  """
│ │ -
│ │  from __future__ import absolute_import
│ │  import warnings
│ │  
│ │  from .connectionpool import (
│ │      HTTPConnectionPool,
│ │      HTTPSConnectionPool,
│ │      connection_from_url
│ │ @@ -23,15 +22,15 @@
│ │  
│ │  # Set default logging handler to avoid "No handler found" warnings.
│ │  import logging
│ │  from logging import NullHandler
│ │  
│ │  __author__ = 'Andrey Petrov ([email protected])'
│ │  __license__ = 'MIT'
│ │ -__version__ = '1.24.1'
│ │ +__version__ = '1.25.3'
│ │  
│ │  __all__ = (
│ │      'HTTPConnectionPool',
│ │      'HTTPSConnectionPool',
│ │      'PoolManager',
│ │      'ProxyManager',
│ │      'HTTPResponse',
│   --- urllib3-1.24.1/dummyserver/certs/cacert.key
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/contrib/appengine.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/appengine.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/packages/backports/makefile.py
├── +++ urllib3-1.25.3/src/urllib3/packages/backports/makefile.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/_implementation.py
├── +++ urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/_implementation.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/proxy.py
├── +++ urllib3-1.25.3/dummyserver/proxy.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/poolmanager.py
├── +++ urllib3-1.25.3/src/urllib3/poolmanager.py
│┄ Files similar despite different names (difference score: 6)
│ │ @@ -3,55 +3,58 @@
│ │  import functools
│ │  import logging
│ │  
│ │  from ._collections import RecentlyUsedContainer
│ │  from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
│ │  from .connectionpool import port_by_scheme
│ │  from .exceptions import LocationValueError, MaxRetryError, ProxySchemeUnknown
│ │ +from .packages import six
│ │  from .packages.six.moves.urllib.parse import urljoin
│ │  from .request import RequestMethods
│ │  from .util.url import parse_url
│ │  from .util.retry import Retry
│ │  
│ │  
│ │  __all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url']
│ │  
│ │  
│ │  log = logging.getLogger(__name__)
│ │  
│ │  SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs',
│ │ -                'ssl_version', 'ca_cert_dir', 'ssl_context')
│ │ +                'ssl_version', 'ca_cert_dir', 'ssl_context',
│ │ +                'key_password')
│ │  
│ │  # All known keyword arguments that could be provided to the pool manager, its
│ │  # pools, or the underlying connections. This is used to construct a pool key.
│ │  _key_fields = (
│ │      'key_scheme',  # str
│ │      'key_host',  # str
│ │      'key_port',  # int
│ │      'key_timeout',  # int or float or Timeout
│ │      'key_retries',  # int or Retry
│ │      'key_strict',  # bool
│ │      'key_block',  # bool
│ │      'key_source_address',  # str
│ │      'key_key_file',  # str
│ │ +    'key_key_password',  # str
│ │      'key_cert_file',  # str
│ │      'key_cert_reqs',  # str
│ │      'key_ca_certs',  # str
│ │      'key_ssl_version',  # str
│ │      'key_ca_cert_dir',  # str
│ │      'key_ssl_context',  # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext
│ │      'key_maxsize',  # int
│ │      'key_headers',  # dict
│ │      'key__proxy',  # parsed proxy url
│ │      'key__proxy_headers',  # dict
│ │      'key_socket_options',  # list of (level (int), optname (int), value (int or str)) tuples
│ │      'key__socks_options',  # dict
│ │      'key_assert_hostname',  # bool or string
│ │      'key_assert_fingerprint',  # str
│ │ -    'key_server_hostname', #str
│ │ +    'key_server_hostname',  # str
│ │  )
│ │  
│ │  #: The namedtuple class used to construct keys for the connection pool.
│ │  #: All custom key schemes should include the fields in this key at a minimum.
│ │  PoolKey = collections.namedtuple('PoolKey', _key_fields)
│ │  
│ │  
│ │ @@ -338,16 +341,18 @@
│ │              retries = Retry.from_int(retries, redirect=redirect)
│ │  
│ │          # Strip headers marked as unsafe to forward to the redirected location.
│ │          # Check remove_headers_on_redirect to avoid a potential network call within
│ │          # conn.is_same_host() which may use socket.gethostbyname() in the future.
│ │          if (retries.remove_headers_on_redirect
│ │                  and not conn.is_same_host(redirect_location)):
│ │ -            for header in retries.remove_headers_on_redirect:
│ │ -                kw['headers'].pop(header, None)
│ │ +            headers = list(six.iterkeys(kw['headers']))
│ │ +            for header in headers:
│ │ +                if header.lower() in retries.remove_headers_on_redirect:
│ │ +                    kw['headers'].pop(header, None)
│ │  
│ │          try:
│ │              retries = retries.increment(method, url, response=response, _pool=conn)
│ │          except MaxRetryError:
│ │              if retries.raise_on_redirect:
│ │                  raise
│ │              return response
│   --- urllib3-1.24.1/src/urllib3/util/connection.py
├── +++ urllib3-1.25.3/src/urllib3/util/connection.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client_no_intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_no_intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/testcase.py
├── +++ urllib3-1.25.3/dummyserver/testcase.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/contrib/test_pyopenssl.py
├── +++ urllib3-1.25.3/test/contrib/test_pyopenssl.py
│┄ Files similar despite different names (difference score: 58)
│ │ @@ -21,21 +21,25 @@
│ │          inject_into_urllib3()
│ │      except ImportError as e:
│ │          pytest.skip('Could not import PyOpenSSL: %r' % e)
│ │  
│ │  
│ │  def teardown_module():
│ │      try:
│ │ -        from urllib3.contrib.securetransport import extract_from_urllib3
│ │ +        from urllib3.contrib.pyopenssl import extract_from_urllib3
│ │          extract_from_urllib3()
│ │      except ImportError:
│ │          pass
│ │  
│ │  
│ │ -from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1  # noqa: F401
│ │ +from ..with_dummyserver.test_https import (  # noqa: F401
│ │ +    TestHTTPS, TestHTTPS_TLSv1, TestHTTPS_TLSv1_1,
│ │ +    TestHTTPS_TLSv1_2, TestHTTPS_TLSv1_3, TestHTTPS_IPSAN,
│ │ +    TestHTTPS_IPv6Addr, TestHTTPS_NoSAN, TestHTTPS_IPV6SAN
│ │ +)
│ │  from ..with_dummyserver.test_socketlevel import (  # noqa: F401
│ │      TestSNI, TestSocketClosing, TestClientCerts
│ │  )
│ │  
│ │  
│ │  class TestPyOpenSSLHelpers(unittest.TestCase):
│ │      """
│   --- urllib3-1.24.1/test/with_dummyserver/test_connectionpool.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_connectionpool.py
│┄ Files similar despite different names (difference score: 3)
│ │ @@ -210,14 +210,16 @@
│ │          # The connect should succeed and this should hit the read timeout
│ │          timeout = Timeout(connect=3, read=5, total=SHORT_TIMEOUT)
│ │          pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False)
│ │          self.addCleanup(pool.close)
│ │          self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
│ │  
│ │      def test_create_connection_timeout(self):
│ │ +        self.start_basic_handler(block_send=Event(), num=0)  # needed for self.port
│ │ +
│ │          timeout = Timeout(connect=SHORT_TIMEOUT, total=LONG_TIMEOUT)
│ │          pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False)
│ │          self.addCleanup(pool.close)
│ │          conn = pool._new_conn()
│ │          self.assertRaises(ConnectTimeoutError, conn.connect)
│ │  
│ │  
│ │ @@ -508,14 +510,31 @@
│ │          """
│ │          for i, line in enumerate(body):
│ │              if line.startswith(b'--'):
│ │                  continue
│ │  
│ │              self.assertEqual(body[i], expected_body[i])
│ │  
│ │ +    def test_post_with_multipart__iter__(self):
│ │ +        data = {'hello': 'world'}
│ │ +        r = self.pool.request('POST', '/echo',
│ │ +                              fields=data,
│ │ +                              preload_content=False,
│ │ +                              multipart_boundary="boundary",
│ │ +                              encode_multipart=True)
│ │ +
│ │ +        chunks = [chunk for chunk in r]
│ │ +        assert chunks == [
│ │ +            b"--boundary\r\n",
│ │ +            b'Content-Disposition: form-data; name="hello"\r\n',
│ │ +            b'\r\n',
│ │ +            b'world\r\n',
│ │ +            b"--boundary--\r\n"
│ │ +        ]
│ │ +
│ │      def test_check_gzip(self):
│ │          r = self.pool.request('GET', '/encodingrequest',
│ │                                headers={'accept-encoding': 'gzip'})
│ │          self.assertEqual(r.headers.get('content-encoding'), 'gzip')
│ │          self.assertEqual(r.data, b'hello, world!')
│ │  
│ │      def test_check_deflate(self):
│   --- urllib3-1.24.1/PKG-INFO
├── +++ urllib3-1.25.3/PKG-INFO
│┄ Files similar despite different names (difference score: 7)
│ │ @@ -1,10 +1,10 @@
│ │  Metadata-Version: 2.1
│ │  Name: urllib3
│ │ -Version: 1.24.1
│ │ +Version: 1.25.3
│ │  Summary: HTTP library with thread-safe connection pooling, file post, and more.
│ │  Home-page: https://urllib3.readthedocs.io/
│ │  Author: Andrey Petrov
│ │  Author-email: [email protected]
│ │  License: MIT
│ │  Description: urllib3
│ │          =======
│ │ @@ -25,33 +25,33 @@
│ │                  :alt: Coverage Status
│ │                  :target: https://codecov.io/gh/urllib3/urllib3
│ │          
│ │          .. image:: https://img.shields.io/pypi/v/urllib3.svg?maxAge=86400
│ │                  :alt: PyPI version
│ │                  :target: https://pypi.org/project/urllib3/
│ │          
│ │ -        .. image:: https://www.bountysource.com/badge/tracker?tracker_id=192525
│ │ -                :alt: Bountysource
│ │ -                :target: https://www.bountysource.com/trackers/192525-urllib3?utm_source=192525&utm_medium=shield&utm_campaign=TRACKER_BADGE
│ │ -        
│ │          .. image:: https://badges.gitter.im/python-urllib3/Lobby.svg
│ │                  :alt: Gitter
│ │                  :target: https://gitter.im/python-urllib3/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
│ │          
│ │ +        .. image:: https://tidelift.com/badges/github/urllib3/urllib3
│ │ +                :alt: Tidelift Dependencies
│ │ +                :target: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=docs
│ │ +        
│ │          urllib3 is a powerful, *sanity-friendly* HTTP client for Python. Much of the
│ │          Python ecosystem already uses urllib3 and you should too.
│ │          urllib3 brings many critical features that are missing from the Python
│ │          standard libraries:
│ │          
│ │          - Thread safety.
│ │          - Connection pooling.
│ │          - Client-side SSL/TLS verification.
│ │          - File uploads with multipart encoding.
│ │          - Helpers for retrying requests and dealing with HTTP redirects.
│ │ -        - Support for gzip and deflate encoding.
│ │ +        - Support for gzip, deflate, and brotli encoding.
│ │          - Proxy support for HTTP and SOCKS.
│ │          - 100% test coverage.
│ │          
│ │          urllib3 is powerful and easy to use::
│ │          
│ │              >>> import urllib3
│ │              >>> http = urllib3.PoolManager()
│ │ @@ -85,50 +85,143 @@
│ │          ------------
│ │          
│ │          urllib3 happily accepts contributions. Please see our
│ │          `contributing documentation <https://urllib3.readthedocs.io/en/latest/contributing.html>`_
│ │          for some tips on getting started.
│ │          
│ │          
│ │ +        Security Disclosures
│ │ +        --------------------
│ │ +        
│ │ +        To report a security vulnerability, please use the
│ │ +        `Tidelift security contact <https://tidelift.com/security>`_.
│ │ +        Tidelift will coordinate the fix and disclosure with maintainers.
│ │ +        
│ │          Maintainers
│ │          -----------
│ │          
│ │          - `@theacodes <https://github.com/theacodes>`_ (Thea Flowers)
│ │ -        - `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_ (Seth M. Larson)
│ │ -        - `@haikuginger <https://github.com/haikuginger>`_ (Jesse Shapiro)
│ │ +        - `@sethmlarson <https://github.com/sethmlarson>`_ (Seth M. Larson)
│ │ +        - `@haikuginger <https://github.com/haikuginger>`_ (Jess Shapiro)
│ │          - `@lukasa <https://github.com/lukasa>`_ (Cory Benfield)
│ │          - `@sigmavirus24 <https://github.com/sigmavirus24>`_ (Ian Cordasco)
│ │          - `@shazow <https://github.com/shazow>`_ (Andrey Petrov)
│ │          
│ │          👋
│ │          
│ │          
│ │          Sponsorship
│ │          -----------
│ │          
│ │ +        .. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
│ │ +           :width: 75
│ │ +           :alt: Tidelift
│ │ +        
│ │ +        .. list-table::
│ │ +           :widths: 10 100
│ │ +        
│ │ +           * - |tideliftlogo|
│ │ +             - Professional support for urllib3 is available as part of the `Tidelift
│ │ +               Subscription`_.  Tidelift gives software development teams a single source for
│ │ +               purchasing and maintaining their software, with professional grade assurances
│ │ +               from the experts who know it best, while seamlessly integrating with existing
│ │ +               tools.
│ │ +        
│ │ +        .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme
│ │ +        
│ │          If your company benefits from this library, please consider `sponsoring its
│ │ -        development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship>`_.
│ │ +        development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship-project-grants>`_.
│ │          
│ │          Sponsors include:
│ │          
│ │          - Google Cloud Platform (2018-present), sponsors `@theacodes <https://github.com/theacodes>`_'s work on an ongoing basis
│ │ -        - Abbott (2018-present), sponsors `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_'s work on an ongoing basis
│ │ -        - Akamai (2017-present), sponsors `@haikuginger <https://github.com/haikuginger>`_'s work on an ongoing basis
│ │ +        - Abbott (2018-present), sponsors `@sethmlarson <https://github.com/sethmlarson>`_'s work on an ongoing basis
│ │ +        - Akamai (2017-2018), sponsored `@haikuginger <https://github.com/haikuginger>`_'s work on urllib3
│ │          - Hewlett Packard Enterprise (2016-2017), sponsored `@Lukasa’s <https://github.com/Lukasa>`_ work on urllib3
│ │          
│ │          
│ │          Changes
│ │          =======
│ │          
│ │ +        1.25.3 (2019-05-23)
│ │ +        -------------------
│ │ +        
│ │ +        * Change ``HTTPSConnection`` to load system CA certificates
│ │ +          when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ +          unspecified. (Pull #1608, Issue #1603)
│ │ +        
│ │ +        * Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +        
│ │ +        
│ │ +        1.25.2 (2019-04-28)
│ │ +        -------------------
│ │ +        
│ │ +        * Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +        
│ │ +        * Change ``parse_url`` to percent-encode invalid characters within the
│ │ +          path, query, and target components. (Pull #1586)
│ │ +        
│ │ +        
│ │ +        1.25.1 (2019-04-24)
│ │ +        -------------------
│ │ +        
│ │ +        * Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +        
│ │ +        * Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +        
│ │ +        
│ │ +        1.25 (2019-04-22)
│ │ +        -----------------
│ │ +        
│ │ +        * Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +        
│ │ +        * Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +        
│ │ +        * Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ +          encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +        
│ │ +        * Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ +          implementations. (Pull #1496)
│ │ +        
│ │ +        * Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +        
│ │ +        * Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ +          given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +        
│ │ +        * Added support for Brotli content encoding. It is enabled automatically if
│ │ +          ``brotlipy`` package is installed which can be requested with
│ │ +          ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +        
│ │ +        * Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ +          Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +        
│ │ +        * Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +        
│ │ +        1.24.3 (2019-05-01)
│ │ +        -------------------
│ │ +        
│ │ +        * Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +        
│ │ +        1.24.2 (2019-04-17)
│ │ +        -------------------
│ │ +        
│ │ +        * Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ +          ``ssl_context`` parameters are specified.
│ │ +        
│ │ +        * Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +        
│ │ +        * Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +        
│ │ +        
│ │          1.24.1 (2018-11-02)
│ │          -------------------
│ │          
│ │          * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │          
│ │ -        * Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ +        * Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │          
│ │          
│ │          1.24 (2018-10-16)
│ │          -----------------
│ │          
│ │          * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│ │          
│ │ @@ -1088,14 +1181,17 @@
│ │  Classifier: Programming Language :: Python
│ │  Classifier: Programming Language :: Python :: 2
│ │  Classifier: Programming Language :: Python :: 2.7
│ │  Classifier: Programming Language :: Python :: 3
│ │  Classifier: Programming Language :: Python :: 3.4
│ │  Classifier: Programming Language :: Python :: 3.5
│ │  Classifier: Programming Language :: Python :: 3.6
│ │ +Classifier: Programming Language :: Python :: 3.7
│ │ +Classifier: Programming Language :: Python :: 3.8
│ │  Classifier: Programming Language :: Python :: Implementation :: CPython
│ │  Classifier: Programming Language :: Python :: Implementation :: PyPy
│ │  Classifier: Topic :: Internet :: WWW/HTTP
│ │  Classifier: Topic :: Software Development :: Libraries
│ │  Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4
│ │  Provides-Extra: socks
│ │  Provides-Extra: secure
│ │ +Provides-Extra: brotli
│   --- urllib3-1.24.1/dummyserver/certs/server.no_san.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.no_san.crt
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/reference/urllib3.util.rst
├── +++ urllib3-1.25.3/docs/reference/urllib3.util.rst
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.key.org
├── +++ urllib3-1.25.3/dummyserver/certs/server.key.org
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/Makefile
├── +++ urllib3-1.25.3/docs/Makefile
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_collections.py
├── +++ urllib3-1.25.3/test/test_collections.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/util/wait.py
├── +++ urllib3-1.25.3/src/urllib3/util/wait.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_wait.py
├── +++ urllib3-1.25.3/test/test_wait.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/test_queue_monkeypatch.py
├── +++ urllib3-1.25.3/test/test_queue_monkeypatch.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/ca_path_test/cacert.pem
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/b6b9ccf9.0
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client_bad.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_bad.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/reference/index.rst
├── +++ urllib3-1.25.3/docs/reference/index.rst
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/with_dummyserver/test_poolmanager.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_poolmanager.py
│┄ Files similar despite different names (difference score: 23)
│ │ @@ -119,14 +119,25 @@
│ │  
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          data = json.loads(r.data.decode('utf-8'))
│ │  
│ │          self.assertNotIn('Authorization', data)
│ │  
│ │ +        r = http.request('GET', '%s/redirect' % self.base_url,
│ │ +                         fields={'target': '%s/headers' % self.base_url_alt},
│ │ +                         headers={'authorization': 'foo'})
│ │ +
│ │ +        self.assertEqual(r.status, 200)
│ │ +
│ │ +        data = json.loads(r.data.decode('utf-8'))
│ │ +
│ │ +        self.assertNotIn('authorization', data)
│ │ +        self.assertNotIn('Authorization', data)
│ │ +
│ │      def test_redirect_cross_host_no_remove_headers(self):
│ │          http = PoolManager()
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/redirect' % self.base_url,
│ │                           fields={'target': '%s/headers' % self.base_url_alt},
│ │                           headers={'Authorization': 'foo'},
│ │ @@ -151,14 +162,28 @@
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          data = json.loads(r.data.decode('utf-8'))
│ │  
│ │          self.assertNotIn('X-API-Secret', data)
│ │          self.assertEqual(data['Authorization'], 'bar')
│ │  
│ │ +        r = http.request('GET', '%s/redirect' % self.base_url,
│ │ +                         fields={'target': '%s/headers' % self.base_url_alt},
│ │ +                         headers={'x-api-secret': 'foo',
│ │ +                                  'authorization': 'bar'},
│ │ +                         retries=Retry(remove_headers_on_redirect=['X-API-Secret']))
│ │ +
│ │ +        self.assertEqual(r.status, 200)
│ │ +
│ │ +        data = json.loads(r.data.decode('utf-8'))
│ │ +
│ │ +        self.assertNotIn('x-api-secret', data)
│ │ +        self.assertNotIn('X-API-Secret', data)
│ │ +        self.assertEqual(data['Authorization'], 'bar')
│ │ +
│ │      def test_raise_on_redirect(self):
│ │          http = PoolManager()
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/redirect' % self.base_url,
│ │                           fields={'target': '%s/redirect?target=%s/' % (self.base_url,
│ │                                                                         self.base_url)},
│   --- urllib3-1.24.1/test/contrib/test_securetransport.py
├── +++ urllib3-1.25.3/test/contrib/test_securetransport.py
│┄ Files similar despite different names (difference score: 51)
│ │ @@ -23,15 +23,18 @@
│ │      try:
│ │          from urllib3.contrib.securetransport import extract_from_urllib3
│ │          extract_from_urllib3()
│ │      except ImportError:
│ │          pass
│ │  
│ │  
│ │ -from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1  # noqa: F401
│ │ +from ..with_dummyserver.test_https import (  # noqa: F401
│ │ +    TestHTTPS, TestHTTPS_TLSv1, TestHTTPS_TLSv1_1,
│ │ +    TestHTTPS_TLSv1_2, TestHTTPS_TLSv1_3
│ │ +)
│ │  from ..with_dummyserver.test_socketlevel import (  # noqa: F401
│ │      TestSNI, TestSocketClosing, TestClientCerts
│ │  )
│ │  
│ │  
│ │  def test_no_crash_with_empty_trust_bundle():
│ │      with contextlib.closing(socket.socket()) as s:
│   --- urllib3-1.24.1/dummyserver/certs/intermediate.key
├── +++ urllib3-1.25.3/dummyserver/certs/intermediate.key
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/response.py
├── +++ urllib3-1.25.3/src/urllib3/response.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -2,14 +2,19 @@
│ │  from contextlib import contextmanager
│ │  import zlib
│ │  import io
│ │  import logging
│ │  from socket import timeout as SocketTimeout
│ │  from socket import error as SocketError
│ │  
│ │ +try:
│ │ +    import brotli
│ │ +except ImportError:
│ │ +    brotli = None
│ │ +
│ │  from ._collections import HTTPHeaderDict
│ │  from .exceptions import (
│ │      BodyNotHttplibCompatible, ProtocolError, DecodeError, ReadTimeoutError,
│ │      ResponseNotChunked, IncompleteRead, InvalidHeader
│ │  )
│ │  from .packages.six import string_types as basestring, PY3
│ │  from .packages.six.moves import http_client as httplib
│ │ @@ -86,14 +91,33 @@
│ │              data = self._obj.unused_data
│ │              if not data:
│ │                  return bytes(ret)
│ │              self._state = GzipDecoderState.OTHER_MEMBERS
│ │              self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
│ │  
│ │  
│ │ +if brotli is not None:
│ │ +    class BrotliDecoder(object):
│ │ +        # Supports both 'brotlipy' and 'Brotli' packages
│ │ +        # since they share an import name. The top branches
│ │ +        # are for 'brotlipy' and bottom branches for 'Brotli'
│ │ +        def __init__(self):
│ │ +            self._obj = brotli.Decompressor()
│ │ +
│ │ +        def decompress(self, data):
│ │ +            if hasattr(self._obj, 'decompress'):
│ │ +                return self._obj.decompress(data)
│ │ +            return self._obj.process(data)
│ │ +
│ │ +        def flush(self):
│ │ +            if hasattr(self._obj, 'flush'):
│ │ +                return self._obj.flush()
│ │ +            return b''
│ │ +
│ │ +
│ │  class MultiDecoder(object):
│ │      """
│ │      From RFC7231:
│ │          If one or more encodings have been applied to a representation, the
│ │          sender that applied the encodings MUST generate a Content-Encoding
│ │          header field that lists the content codings in the order in which
│ │          they were applied.
│ │ @@ -114,14 +138,17 @@
│ │  def _get_decoder(mode):
│ │      if ',' in mode:
│ │          return MultiDecoder(mode)
│ │  
│ │      if mode == 'gzip':
│ │          return GzipDecoder()
│ │  
│ │ +    if brotli is not None and mode == 'br':
│ │ +        return BrotliDecoder()
│ │ +
│ │      return DeflateDecoder()
│ │  
│ │  
│ │  class HTTPResponse(io.IOBase):
│ │      """
│ │      HTTP Response container.
│ │  
│ │ @@ -151,14 +178,16 @@
│ │  
│ │      :param enforce_content_length:
│ │          Enforce content length checking. Body returned by server must match
│ │          value of Content-Length header, if present. Otherwise, raise error.
│ │      """
│ │  
│ │      CONTENT_DECODERS = ['gzip', 'deflate']
│ │ +    if brotli is not None:
│ │ +        CONTENT_DECODERS += ['br']
│ │      REDIRECT_STATUSES = [301, 302, 303, 307, 308]
│ │  
│ │      def __init__(self, body='', headers=None, status=0, version=0, reason=None,
│ │                   strict=0, preload_content=True, decode_content=True,
│ │                   original_response=None, pool=None, connection=None, msg=None,
│ │                   retries=None, enforce_content_length=False,
│ │                   request_method=None, request_url=None):
│ │ @@ -307,32 +336,40 @@
│ │          # Note: content-encoding value should be case-insensitive, per RFC 7230
│ │          # Section 3.2
│ │          content_encoding = self.headers.get('content-encoding', '').lower()
│ │          if self._decoder is None:
│ │              if content_encoding in self.CONTENT_DECODERS:
│ │                  self._decoder = _get_decoder(content_encoding)
│ │              elif ',' in content_encoding:
│ │ -                encodings = [e.strip() for e in content_encoding.split(',') if e.strip() in self.CONTENT_DECODERS]
│ │ +                encodings = [
│ │ +                    e.strip() for e in content_encoding.split(',')
│ │ +                    if e.strip() in self.CONTENT_DECODERS]
│ │                  if len(encodings):
│ │                      self._decoder = _get_decoder(content_encoding)
│ │  
│ │ +    DECODER_ERROR_CLASSES = (IOError, zlib.error)
│ │ +    if brotli is not None:
│ │ +        DECODER_ERROR_CLASSES += (brotli.error,)
│ │ +
│ │      def _decode(self, data, decode_content, flush_decoder):
│ │          """
│ │          Decode the data passed in and potentially flush the decoder.
│ │          """
│ │ +        if not decode_content:
│ │ +            return data
│ │ +
│ │          try:
│ │ -            if decode_content and self._decoder:
│ │ +            if self._decoder:
│ │                  data = self._decoder.decompress(data)
│ │ -        except (IOError, zlib.error) as e:
│ │ +        except self.DECODER_ERROR_CLASSES as e:
│ │              content_encoding = self.headers.get('content-encoding', '').lower()
│ │              raise DecodeError(
│ │                  "Received response with content-encoding: %s, but "
│ │                  "failed to decode it." % content_encoding, e)
│ │ -
│ │ -        if flush_decoder and decode_content:
│ │ +        if flush_decoder:
│ │              data += self._flush_decoder()
│ │  
│ │          return data
│ │  
│ │      def _flush_decoder(self):
│ │          """
│ │          Flushes the decoder. Should only be called if the decoder is actually
│ │ @@ -504,17 +541,18 @@
│ │  
│ │          Remaining parameters are passed to the HTTPResponse constructor, along
│ │          with ``original_response=r``.
│ │          """
│ │          headers = r.msg
│ │  
│ │          if not isinstance(headers, HTTPHeaderDict):
│ │ -            if PY3:  # Python 3
│ │ +            if PY3:
│ │                  headers = HTTPHeaderDict(headers.items())
│ │ -            else:  # Python 2
│ │ +            else:
│ │ +                # Python 2.7
│ │                  headers = HTTPHeaderDict.from_httplib(headers)
│ │  
│ │          # HTTPResponse objects in Python 3 don't have a .strict attribute
│ │          strict = getattr(r, 'strict', 0)
│ │          resp = ResponseCls(body=r,
│ │                             headers=headers,
│ │                             status=r.status,
│ │ @@ -699,7 +737,24 @@
│ │          If the request that generated this response redirected, this method
│ │          will return the final redirect location.
│ │          """
│ │          if self.retries is not None and len(self.retries.history):
│ │              return self.retries.history[-1].redirect_location
│ │          else:
│ │              return self._request_url
│ │ +
│ │ +    def __iter__(self):
│ │ +        buffer = [b""]
│ │ +        for chunk in self.stream(decode_content=True):
│ │ +            if b"\n" in chunk:
│ │ +                chunk = chunk.split(b"\n")
│ │ +                yield b"".join(buffer) + chunk[0] + b"\n"
│ │ +                for x in chunk[1:-1]:
│ │ +                    yield x + b"\n"
│ │ +                if chunk[-1]:
│ │ +                    buffer = [chunk[-1]]
│ │ +                else:
│ │ +                    buffer = []
│ │ +            else:
│ │ +                buffer.append(chunk)
│ │ +        if buffer:
│ │ +            yield b"".join(buffer)
│   --- urllib3-1.24.1/docs/advanced-usage.rst
├── +++ urllib3-1.25.3/docs/advanced-usage.rst
│┄ Files similar despite different names (difference score: 27)
│ │ @@ -135,16 +135,16 @@
│ │      >>> from urllib3.contrib.socks import SOCKSProxyManager
│ │      >>> proxy = SOCKSProxyManager('socks5://localhost:8889/')
│ │      >>> proxy.request('GET', 'http://google.com/')
│ │  
│ │  
│ │  .. _ssl_custom:
│ │  
│ │ -Custom SSL certificates and client certificates
│ │ ------------------------------------------------
│ │ +Custom SSL certificates
│ │ +-----------------------
│ │  
│ │  Instead of using `certifi <https://certifi.io/>`_ you can provide your
│ │  own certificate authority bundle. This is useful for cases where you've
│ │  generated your own certificates or when you're using a private certificate
│ │  authority. Just provide the full path to the certificate bundle when creating a
│ │  :class:`~poolmanager.PoolManager`::
│ │  
│ │ @@ -154,24 +154,40 @@
│ │      ...     ca_certs='/path/to/your/certificate_bundle')
│ │  
│ │  When you specify your own certificate bundle only requests that can be
│ │  verified with that bundle will succeed. It's recommended to use a separate
│ │  :class:`~poolmanager.PoolManager` to make requests to URLs that do not need
│ │  the custom certificate.
│ │  
│ │ +.. _ssl_client:
│ │ +
│ │ +Client certificates
│ │ +-------------------
│ │ +
│ │  You can also specify a client certificate. This is useful when both the server
│ │  and the client need to verify each other's identity. Typically these
│ │  certificates are issued from the same authority. To use a client certificate,
│ │  provide the full path when creating a :class:`~poolmanager.PoolManager`::
│ │  
│ │      >>> http = urllib3.PoolManager(
│ │      ...     cert_file='/path/to/your/client_cert.pem',
│ │      ...     cert_reqs='CERT_REQUIRED',
│ │      ...     ca_certs='/path/to/your/certificate_bundle')
│ │  
│ │ +If you have an encrypted client certificate private key you can use
│ │ +the ``key_password`` parameter to specify a password to decrypt the key. ::
│ │ +
│ │ +    >>> http = urllib3.PoolManager(
│ │ +    ...     cert_file='/path/to/your/client_cert.pem',
│ │ +    ...     cert_reqs='CERT_REQUIRED',
│ │ +    ...     key_file='/path/to/your/client.key',
│ │ +    ...     key_password='keyfile_password')
│ │ +
│ │ +If your key isn't encrypted the ``key_password`` parameter isn't required.
│ │ +
│ │  .. _ssl_mac:
│ │  
│ │  Certificate validation and Mac OS X
│ │  -----------------------------------
│ │  
│ │  Apple-provided Python and OpenSSL libraries contain a patches that make them
│ │  automatically check the system keychain's certificates. This can be
│ │ @@ -186,15 +202,15 @@
│ │  
│ │  .. _ssl_warnings:
│ │  
│ │  SSL Warnings
│ │  ------------
│ │  
│ │  urllib3 will issue several different warnings based on the level of certificate
│ │ -verification support. These warning indicate particular situations and can
│ │ +verification support. These warnings indicate particular situations and can
│ │  be resolved in different ways.
│ │  
│ │  * :class:`~exceptions.InsecureRequestWarning`
│ │      This happens when a request is made to an HTTPS URL without certificate
│ │      verification enabled. Follow the :ref:`certificate verification <ssl>`
│ │      guide to resolve this warning.
│ │  * :class:`~exceptions.InsecurePlatformWarning`
│ │ @@ -253,7 +269,23 @@
│ │  :class:`~urllib3.poolmanager.PoolManager` as usual::
│ │  
│ │      env_variables:
│ │          GAE_USE_SOCKETS_HTTPLIB : 'true'
│ │  
│ │  For more details on the limitations and gotchas, see
│ │  :mod:`urllib3.contrib.appengine`.
│ │ +
│ │ +Brotli Encoding
│ │ +---------------
│ │ +
│ │ +Brotli is a compression algorithm created by Google with better compression
│ │ +than gzip and deflate and is supported by urllib3 if the
│ │ +`brotlipy <https://github.com/python-hyper/brotlipy>`_ package is installed.
│ │ +You may also request the package be installed via the ``urllib3[brotli]`` extra::
│ │ +
│ │ +    python -m pip install urllib3[brotli]
│ │ +
│ │ +Here's an example using brotli encoding via the ``Accept-Encoding`` header::
│ │ +
│ │ +    >>> from urllib3 import PoolManager
│ │ +    >>> http = PoolManager()
│ │ +    >>> http.request('GET', 'https://www.google.com/', headers={'Accept-Encoding': 'br'})
│   --- urllib3-1.24.1/test/test_proxymanager.py
├── +++ urllib3-1.25.3/test/test_proxymanager.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/docs/index.rst
├── +++ urllib3-1.25.3/docs/index.rst
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/with_dummyserver/test_https.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_https.py
│┄ Files similar despite different names (difference score: 15)
│ │ @@ -13,26 +13,33 @@
│ │      HTTPSDummyServerTestCase, IPV6HTTPSDummyServerTestCase
│ │  )
│ │  from dummyserver.server import (DEFAULT_CA, DEFAULT_CA_BAD, DEFAULT_CERTS,
│ │                                  DEFAULT_CLIENT_CERTS,
│ │                                  DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS,
│ │                                  NO_SAN_CERTS, NO_SAN_CA, DEFAULT_CA_DIR,
│ │                                  IPV6_ADDR_CERTS, IPV6_ADDR_CA, HAS_IPV6,
│ │ -                                IP_SAN_CERTS)
│ │ +                                IP_SAN_CERTS, IPV6_SAN_CERTS, IPV6_SAN_CA,
│ │ +                                PASSWORD_CLIENT_KEYFILE)
│ │  
│ │  from test import (
│ │      onlyPy279OrNewer,
│ │      notSecureTransport,
│ │ +    notOpenSSL098,
│ │      requires_network,
│ │ +    requires_ssl_context_keyfile_password,
│ │ +    fails_on_travis_gce,
│ │ +    requiresTLSv1,
│ │ +    requiresTLSv1_1,
│ │ +    requiresTLSv1_2,
│ │ +    requiresTLSv1_3,
│ │      TARPIT_HOST,
│ │  )
│ │  from urllib3 import HTTPSConnectionPool
│ │  from urllib3.connection import (
│ │      VerifiedHTTPSConnection,
│ │ -    UnverifiedHTTPSConnection,
│ │      RECENT_DATE,
│ │  )
│ │  from urllib3.exceptions import (
│ │      SSLError,
│ │      ConnectTimeoutError,
│ │      InsecureRequestWarning,
│ │      SystemTimeWarning,
│ │ @@ -51,54 +58,64 @@
│ │  
│ │  
│ │  log = logging.getLogger('urllib3.connectionpool')
│ │  log.setLevel(logging.NOTSET)
│ │  log.addHandler(logging.StreamHandler(sys.stdout))
│ │  
│ │  
│ │ +TLSv1_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1", None)
│ │ +
│ │ +TLSv1_1_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_1_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1_1", None)
│ │ +
│ │ +TLSv1_2_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_2_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1_2", None)
│ │ +
│ │ +
│ │  class TestHTTPS(HTTPSDummyServerTestCase):
│ │ +    tls_protocol_name = None
│ │ +
│ │      def setUp(self):
│ │ -        self._pool = HTTPSConnectionPool(self.host, self.port)
│ │ +        self._pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(self._pool.close)
│ │  
│ │      def test_simple(self):
│ │          r = self._pool.request('GET', '/')
│ │          self.assertEqual(r.status, 200, r.data)
│ │  
│ │ +    @fails_on_travis_gce
│ │      def test_dotted_fqdn(self):
│ │ -        pool = HTTPSConnectionPool(self.host + '.', self.port)
│ │ +        pool = HTTPSConnectionPool(self.host + '.', self.port, ca_certs=DEFAULT_CA)
│ │          r = pool.request('GET', '/')
│ │          self.assertEqual(r.status, 200, r.data)
│ │  
│ │ -    def test_set_ssl_version_to_tlsv1(self):
│ │ -        self._pool.ssl_version = ssl.PROTOCOL_TLSv1
│ │ -        r = self._pool.request('GET', '/')
│ │ -        self.assertEqual(r.status, 200, r.data)
│ │ -
│ │      def test_client_intermediate(self):
│ │          client_cert, client_key = (
│ │              DEFAULT_CLIENT_CERTS['certfile'],
│ │              DEFAULT_CLIENT_CERTS['keyfile'],
│ │          )
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           key_file=client_key,
│ │ -                                         cert_file=client_cert)
│ │ +                                         cert_file=client_cert,
│ │ +                                         ca_certs=DEFAULT_CA)
│ │          r = https_pool.request('GET', '/certificate')
│ │          subject = json.loads(r.data.decode('utf-8'))
│ │          assert subject['organizationalUnitName'].startswith(
│ │              'Testing server cert')
│ │  
│ │      def test_client_no_intermediate(self):
│ │          client_cert, client_key = (
│ │              DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['certfile'],
│ │              DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['keyfile']
│ │          )
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           cert_file=client_cert,
│ │ -                                         key_file=client_key)
│ │ +                                         key_file=client_key,
│ │ +                                         ca_certs=DEFAULT_CA)
│ │          try:
│ │              https_pool.request('GET', '/certificate', retries=False)
│ │          except SSLError as e:
│ │              if not ('alert unknown ca' in str(e) or
│ │                      'invalid certificate chain' in str(e) or
│ │                      'unknown Cert Authority' in str(e) or
│ │                      # https://github.com/urllib3/urllib3/issues/1422
│ │ @@ -106,14 +123,47 @@
│ │                      'WSAECONNRESET' in str(e)):
│ │                  raise
│ │          except ProtocolError as e:
│ │              # https://github.com/urllib3/urllib3/issues/1422
│ │              if not ('An existing connection was forcibly closed by the remote host' in str(e)):
│ │                  raise
│ │  
│ │ +    @requires_ssl_context_keyfile_password
│ │ +    def test_client_key_password(self):
│ │ +        client_cert, client_key = (
│ │ +            DEFAULT_CLIENT_CERTS['certfile'],
│ │ +            PASSWORD_CLIENT_KEYFILE,
│ │ +        )
│ │ +        https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ +                                         ca_certs=DEFAULT_CA,
│ │ +                                         key_file=client_key,
│ │ +                                         cert_file=client_cert,
│ │ +                                         key_password="letmein")
│ │ +        r = https_pool.request('GET', '/certificate')
│ │ +        subject = json.loads(r.data.decode('utf-8'))
│ │ +        assert subject['organizationalUnitName'].startswith(
│ │ +            'Testing server cert')
│ │ +
│ │ +    @requires_ssl_context_keyfile_password
│ │ +    def test_client_encrypted_key_requires_password(self):
│ │ +        client_cert, client_key = (
│ │ +            DEFAULT_CLIENT_CERTS['certfile'],
│ │ +            PASSWORD_CLIENT_KEYFILE,
│ │ +        )
│ │ +        https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ +                                         key_file=client_key,
│ │ +                                         cert_file=client_cert,
│ │ +                                         key_password=None)
│ │ +
│ │ +        with pytest.raises(MaxRetryError) as e:
│ │ +            https_pool.request('GET', '/certificate')
│ │ +
│ │ +        assert 'password is required' in str(e.value)
│ │ +        assert isinstance(e.value.reason, SSLError)
│ │ +
│ │      def test_verified(self):
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           cert_reqs='CERT_REQUIRED',
│ │                                           ca_certs=DEFAULT_CA)
│ │          self.addCleanup(https_pool.close)
│ │  
│ │          conn = https_pool._new_conn()
│ │ @@ -191,14 +241,15 @@
│ │                  else:
│ │                      call = warn.call_args_list[1]
│ │                  error = call[0][1]
│ │                  self.assertEqual(error, InsecurePlatformWarning)
│ │  
│ │      @onlyPy279OrNewer
│ │      @notSecureTransport  # SecureTransport does not support cert directories
│ │ +    @notOpenSSL098  # OpenSSL 0.9.8 does not support cert directories
│ │      def test_ca_dir_verified(self):
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           cert_reqs='CERT_REQUIRED',
│ │                                           ca_cert_dir=DEFAULT_CA_DIR)
│ │          self.addCleanup(https_pool.close)
│ │  
│ │          conn = https_pool._new_conn()
│ │ @@ -269,16 +320,15 @@
│ │          self.assertRaises(SSLError, pool._new_conn)
│ │          with self.assertRaises(MaxRetryError) as cm:
│ │              pool.request('GET', '/', retries=0)
│ │          self.assertIsInstance(cm.exception.reason, SSLError)
│ │  
│ │      def test_unverified_ssl(self):
│ │          """ Test that bare HTTPSConnection can connect, make requests """
│ │ -        pool = HTTPSConnectionPool(self.host, self.port)
│ │ -        pool.ConnectionCls = UnverifiedHTTPSConnection
│ │ +        pool = HTTPSConnectionPool(self.host, self.port, cert_reqs=ssl.CERT_NONE)
│ │          self.addCleanup(pool.close)
│ │  
│ │          with mock.patch('warnings.warn') as warn:
│ │              r = pool.request('GET', '/')
│ │              self.assertEqual(r.status, 200)
│ │              self.assertTrue(warn.called)
│ │  
│ │ @@ -453,15 +503,15 @@
│ │          timeout = Timeout(total=None, connect=0.001)
│ │          https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port,
│ │                                           timeout=timeout, retries=False,
│ │                                           cert_reqs='CERT_REQUIRED')
│ │          self.addCleanup(https_pool.close)
│ │          self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/')
│ │  
│ │ -        timeout = Timeout(read=0.001)
│ │ +        timeout = Timeout(read=0.01)
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           timeout=timeout, retries=False,
│ │                                           cert_reqs='CERT_REQUIRED')
│ │          self.addCleanup(https_pool.close)
│ │          https_pool.ca_certs = DEFAULT_CA
│ │          https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \
│ │                                          'BF:93:CF:F9:71:CC:07:7D:0A'
│ │ @@ -510,23 +560,22 @@
│ │          conn = https_pool._new_conn()
│ │          self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/',
│ │                            timeout=Timeout(total=None, connect=0.001))
│ │  
│ │      def test_enhanced_ssl_connection(self):
│ │          fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:BF:93:CF:F9:71:CC:07:7D:0A'
│ │  
│ │ -        conn = VerifiedHTTPSConnection(self.host, self.port)
│ │ -        self.addCleanup(conn.close)
│ │          https_pool = HTTPSConnectionPool(self.host, self.port,
│ │                                           cert_reqs='CERT_REQUIRED',
│ │                                           ca_certs=DEFAULT_CA,
│ │                                           assert_fingerprint=fingerprint)
│ │          self.addCleanup(https_pool.close)
│ │  
│ │ -        https_pool._make_request(conn, 'GET', '/')
│ │ +        r = https_pool.request('GET', '/')
│ │ +        assert r.status == 200
│ │  
│ │      @onlyPy279OrNewer
│ │      def test_ssl_correct_system_time(self):
│ │          self._pool.cert_reqs = 'CERT_REQUIRED'
│ │          self._pool.ca_certs = DEFAULT_CA
│ │  
│ │          w = self._request_without_resource_warnings('GET', '/')
│ │ @@ -550,35 +599,61 @@
│ │      def _request_without_resource_warnings(self, method, url):
│ │          with warnings.catch_warnings(record=True) as w:
│ │              warnings.simplefilter('always')
│ │              self._pool.request(method, url)
│ │  
│ │          return [x for x in w if not isinstance(x.message, ResourceWarning)]
│ │  
│ │ +    def test_set_ssl_version_to_tls_version(self):
│ │ +        if self.tls_protocol_name is None:
│ │ +            pytest.skip("Skipping base test class")
│ │  
│ │ -class TestHTTPS_TLSv1(HTTPSDummyServerTestCase):
│ │ -    certs = DEFAULT_CERTS.copy()
│ │ -    certs['ssl_version'] = ssl.PROTOCOL_TLSv1
│ │ -
│ │ -    def setUp(self):
│ │ -        self._pool = HTTPSConnectionPool(self.host, self.port)
│ │ -        self.addCleanup(self._pool.close)
│ │ -
│ │ -    def test_discards_connection_on_sslerror(self):
│ │ -        self._pool.cert_reqs = 'CERT_REQUIRED'
│ │ -        with self.assertRaises(MaxRetryError) as cm:
│ │ -            self._pool.request('GET', '/', retries=0)
│ │ -        self.assertIsInstance(cm.exception.reason, SSLError)
│ │ -        self._pool.ca_certs = DEFAULT_CA
│ │ -        self._pool.request('GET', '/')
│ │ +        self._pool.ssl_version = self.certs['ssl_version']
│ │ +        r = self._pool.request('GET', '/')
│ │ +        self.assertEqual(r.status, 200, r.data)
│ │  
│ │      def test_set_cert_default_cert_required(self):
│ │          conn = VerifiedHTTPSConnection(self.host, self.port)
│ │ -        conn.set_cert(ca_certs=DEFAULT_CA)
│ │ -        self.assertEqual(conn.cert_reqs, 'CERT_REQUIRED')
│ │ +        conn.set_cert()
│ │ +        self.assertEqual(conn.cert_reqs, ssl.CERT_REQUIRED)
│ │ +
│ │ +    def test_tls_protocol_name_of_socket(self):
│ │ +        if self.tls_protocol_name is None:
│ │ +            pytest.skip("Skipping base test class")
│ │ +
│ │ +        conn = self._pool._get_conn()
│ │ +        conn.connect()
│ │ +
│ │ +        if not hasattr(conn.sock, 'version'):
│ │ +            pytest.skip('SSLSocket.version() not available')
│ │ +
│ │ +        self.assertEqual(conn.sock.version(), self.tls_protocol_name)
│ │ +
│ │ +
│ │ +@requiresTLSv1()
│ │ +class TestHTTPS_TLSv1(TestHTTPS):
│ │ +    tls_protocol_name = 'TLSv1'
│ │ +    certs = TLSv1_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_1()
│ │ +class TestHTTPS_TLSv1_1(TestHTTPS):
│ │ +    tls_protocol_name = 'TLSv1.1'
│ │ +    certs = TLSv1_1_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_2()
│ │ +class TestHTTPS_TLSv1_2(TestHTTPS):
│ │ +    tls_protocol_name = 'TLSv1.2'
│ │ +    certs = TLSv1_2_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_3()
│ │ +class TestHTTPS_TLSv1_3(TestHTTPS):
│ │ +    tls_protocol_name = 'TLSv1.3'
│ │  
│ │  
│ │  class TestHTTPS_NoSAN(HTTPSDummyServerTestCase):
│ │      certs = NO_SAN_CERTS
│ │  
│ │      def test_warning_for_certs_without_a_san(self):
│ │          """Ensure that a warning is raised when the cert from the server has
│ │ @@ -621,9 +696,27 @@
│ │                                           cert_reqs='CERT_REQUIRED',
│ │                                           ca_certs=IPV6_ADDR_CA)
│ │          self.addCleanup(https_pool.close)
│ │          r = https_pool.request('GET', '/')
│ │          self.assertEqual(r.status, 200)
│ │  
│ │  
│ │ +class TestHTTPS_IPV6SAN(IPV6HTTPSDummyServerTestCase):
│ │ +    certs = IPV6_SAN_CERTS
│ │ +
│ │ +    def test_can_validate_ipv6_san(self):
│ │ +        """Ensure that urllib3 can validate SANs with IPv6 addresses in them."""
│ │ +        try:
│ │ +            import ipaddress  # noqa: F401
│ │ +        except ImportError:
│ │ +            pytest.skip("Only runs on systems with an ipaddress module")
│ │ +
│ │ +        https_pool = HTTPSConnectionPool('[::1]', self.port,
│ │ +                                         cert_reqs='CERT_REQUIRED',
│ │ +                                         ca_certs=IPV6_SAN_CA)
│ │ +        self.addCleanup(https_pool.close)
│ │ +        r = https_pool.request('GET', '/')
│ │ +        self.assertEqual(r.status, 200)
│ │ +
│ │ +
│ │  if __name__ == '__main__':
│ │      unittest.main()
│   --- urllib3-1.24.1/test/port_helpers.py
├── +++ urllib3-1.25.3/test/port_helpers.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/ca_path_test/b6b9ccf9.0
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/cacert.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/contrib/securetransport.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/securetransport.py
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -19,14 +19,39 @@
│ │  
│ │  To use this module, simply import and inject it::
│ │  
│ │      import urllib3.contrib.securetransport
│ │      urllib3.contrib.securetransport.inject_into_urllib3()
│ │  
│ │  Happy TLSing!
│ │ +
│ │ +This code is a bastardised version of the code found in Will Bond's oscrypto
│ │ +library. An enormous debt is owed to him for blazing this trail for us. For
│ │ +that reason, this code should be considered to be covered both by urllib3's
│ │ +license and by oscrypto's:
│ │ +
│ │ +    Copyright (c) 2015-2016 Will Bond <[email protected]>
│ │ +
│ │ +    Permission is hereby granted, free of charge, to any person obtaining a
│ │ +    copy of this software and associated documentation files (the "Software"),
│ │ +    to deal in the Software without restriction, including without limitation
│ │ +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
│ │ +    and/or sell copies of the Software, and to permit persons to whom the
│ │ +    Software is furnished to do so, subject to the following conditions:
│ │ +
│ │ +    The above copyright notice and this permission notice shall be included in
│ │ +    all copies or substantial portions of the Software.
│ │ +
│ │ +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
│ │ +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
│ │ +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
│ │ +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
│ │ +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
│ │ +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
│ │ +    DEALINGS IN THE SOFTWARE.
│ │  """
│ │  from __future__ import absolute_import
│ │  
│ │  import contextlib
│ │  import ctypes
│ │  import errno
│ │  import os.path
│ │ @@ -82,53 +107,51 @@
│ │  # for no better reason than we need *a* limit, and this one is right there.
│ │  SSL_WRITE_BLOCKSIZE = 16384
│ │  
│ │  # This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to
│ │  # individual cipher suites. We need to do this because this is how
│ │  # SecureTransport wants them.
│ │  CIPHER_SUITES = [
│ │ -    SecurityConst.TLS_AES_256_GCM_SHA384,
│ │ -    SecurityConst.TLS_CHACHA20_POLY1305_SHA256,
│ │ -    SecurityConst.TLS_AES_128_GCM_SHA256,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
│ │ -    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
│ │ +    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
│ │      SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
│ │ +    SecurityConst.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
│ │ +    SecurityConst.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
│ │      SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
│ │      SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
│ │ -    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
│ │ -    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
│ │ -    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
│ │ -    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
│ │ -    SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
│ │      SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
│ │ +    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
│ │ +    SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
│ │ +    SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
│ │      SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
│ │ +    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
│ │ +    SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
│ │      SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
│ │      SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
│ │ -    SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
│ │ +    SecurityConst.TLS_AES_256_GCM_SHA384,
│ │ +    SecurityConst.TLS_AES_128_GCM_SHA256,
│ │      SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384,
│ │      SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256,
│ │ +    SecurityConst.TLS_AES_128_CCM_8_SHA256,
│ │ +    SecurityConst.TLS_AES_128_CCM_SHA256,
│ │      SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256,
│ │      SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256,
│ │      SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA,
│ │      SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA,
│ │  ]
│ │  
│ │  # Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of
│ │ -# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version.
│ │ +# TLSv1 and a high of TLSv1.3. For everything else, we pin to that version.
│ │ +# TLSv1 to 1.2 are supported on macOS 10.8+ and TLSv1.3 is macOS 10.13+
│ │  _protocol_to_min_max = {
│ │ -    ssl.PROTOCOL_SSLv23: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12),
│ │ +    util.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocolMaxSupported),
│ │  }
│ │  
│ │  if hasattr(ssl, "PROTOCOL_SSLv2"):
│ │      _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = (
│ │          SecurityConst.kSSLProtocol2, SecurityConst.kSSLProtocol2
│ │      )
│ │  if hasattr(ssl, "PROTOCOL_SSLv3"):
│ │ @@ -143,33 +166,33 @@
│ │      _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = (
│ │          SecurityConst.kTLSProtocol11, SecurityConst.kTLSProtocol11
│ │      )
│ │  if hasattr(ssl, "PROTOCOL_TLSv1_2"):
│ │      _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = (
│ │          SecurityConst.kTLSProtocol12, SecurityConst.kTLSProtocol12
│ │      )
│ │ -if hasattr(ssl, "PROTOCOL_TLS"):
│ │ -    _protocol_to_min_max[ssl.PROTOCOL_TLS] = _protocol_to_min_max[ssl.PROTOCOL_SSLv23]
│ │  
│ │  
│ │  def inject_into_urllib3():
│ │      """
│ │      Monkey-patch urllib3 with SecureTransport-backed SSL-support.
│ │      """
│ │ +    util.SSLContext = SecureTransportContext
│ │      util.ssl_.SSLContext = SecureTransportContext
│ │      util.HAS_SNI = HAS_SNI
│ │      util.ssl_.HAS_SNI = HAS_SNI
│ │      util.IS_SECURETRANSPORT = True
│ │      util.ssl_.IS_SECURETRANSPORT = True
│ │  
│ │  
│ │  def extract_from_urllib3():
│ │      """
│ │      Undo monkey-patching by :func:`inject_into_urllib3`.
│ │      """
│ │ +    util.SSLContext = orig_util_SSLContext
│ │      util.ssl_.SSLContext = orig_util_SSLContext
│ │      util.HAS_SNI = orig_util_HAS_SNI
│ │      util.ssl_.HAS_SNI = orig_util_HAS_SNI
│ │      util.IS_SECURETRANSPORT = False
│ │      util.ssl_.IS_SECURETRANSPORT = False
│ │  
│ │  
│ │ @@ -454,15 +477,22 @@
│ │  
│ │          # Setup the ciphers.
│ │          self._set_ciphers()
│ │  
│ │          # Set the minimum and maximum TLS versions.
│ │          result = Security.SSLSetProtocolVersionMin(self.context, min_version)
│ │          _assert_no_error(result)
│ │ +
│ │ +        # TLS 1.3 isn't necessarily enabled by the OS
│ │ +        # so we have to detect when we error out and try
│ │ +        # setting TLS 1.3 if it's allowed. kTLSProtocolMaxSupported
│ │ +        # was added in macOS 10.13 along with kTLSProtocol13.
│ │          result = Security.SSLSetProtocolVersionMax(self.context, max_version)
│ │ +        if result != 0 and max_version == SecurityConst.kTLSProtocolMaxSupported:
│ │ +            result = Security.SSLSetProtocolVersionMax(self.context, SecurityConst.kTLSProtocol12)
│ │          _assert_no_error(result)
│ │  
│ │          # If there's a trust DB, we need to use it. We do that by telling
│ │          # SecureTransport to break on server auth. We also do that if we don't
│ │          # want to validate the certs at all: we just won't actually do any
│ │          # authing in that case.
│ │          if not verify or trust_bundle is not None:
│ │ @@ -663,14 +693,33 @@
│ │              if certdata:
│ │                  CoreFoundation.CFRelease(certdata)
│ │              if trust:
│ │                  CoreFoundation.CFRelease(trust)
│ │  
│ │          return der_bytes
│ │  
│ │ +    def version(self):
│ │ +        protocol = Security.SSLProtocol()
│ │ +        result = Security.SSLGetNegotiatedProtocolVersion(self.context, ctypes.byref(protocol))
│ │ +        _assert_no_error(result)
│ │ +        if protocol.value == SecurityConst.kTLSProtocol13:
│ │ +            return 'TLSv1.3'
│ │ +        elif protocol.value == SecurityConst.kTLSProtocol12:
│ │ +            return 'TLSv1.2'
│ │ +        elif protocol.value == SecurityConst.kTLSProtocol11:
│ │ +            return 'TLSv1.1'
│ │ +        elif protocol.value == SecurityConst.kTLSProtocol1:
│ │ +            return 'TLSv1'
│ │ +        elif protocol.value == SecurityConst.kSSLProtocol3:
│ │ +            return 'SSLv3'
│ │ +        elif protocol.value == SecurityConst.kSSLProtocol2:
│ │ +            return 'SSLv2'
│ │ +        else:
│ │ +            raise ssl.SSLError('Unknown TLS version: %r' % protocol)
│ │ +
│ │      def _reuse(self):
│ │          self._makefile_refs += 1
│ │  
│ │      def _drop(self):
│ │          if self._makefile_refs < 1:
│ │              self.close()
│ │          else:
│   --- urllib3-1.24.1/src/urllib3/exceptions.py
├── +++ urllib3-1.25.3/src/urllib3/exceptions.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3.egg-info/PKG-INFO
├── +++ urllib3-1.25.3/src/urllib3.egg-info/PKG-INFO
│┄ Files similar despite different names (difference score: 7)
│ │ @@ -1,10 +1,10 @@
│ │  Metadata-Version: 2.1
│ │  Name: urllib3
│ │ -Version: 1.24.1
│ │ +Version: 1.25.3
│ │  Summary: HTTP library with thread-safe connection pooling, file post, and more.
│ │  Home-page: https://urllib3.readthedocs.io/
│ │  Author: Andrey Petrov
│ │  Author-email: [email protected]
│ │  License: MIT
│ │  Description: urllib3
│ │          =======
│ │ @@ -25,33 +25,33 @@
│ │                  :alt: Coverage Status
│ │                  :target: https://codecov.io/gh/urllib3/urllib3
│ │          
│ │          .. image:: https://img.shields.io/pypi/v/urllib3.svg?maxAge=86400
│ │                  :alt: PyPI version
│ │                  :target: https://pypi.org/project/urllib3/
│ │          
│ │ -        .. image:: https://www.bountysource.com/badge/tracker?tracker_id=192525
│ │ -                :alt: Bountysource
│ │ -                :target: https://www.bountysource.com/trackers/192525-urllib3?utm_source=192525&utm_medium=shield&utm_campaign=TRACKER_BADGE
│ │ -        
│ │          .. image:: https://badges.gitter.im/python-urllib3/Lobby.svg
│ │                  :alt: Gitter
│ │                  :target: https://gitter.im/python-urllib3/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
│ │          
│ │ +        .. image:: https://tidelift.com/badges/github/urllib3/urllib3
│ │ +                :alt: Tidelift Dependencies
│ │ +                :target: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=docs
│ │ +        
│ │          urllib3 is a powerful, *sanity-friendly* HTTP client for Python. Much of the
│ │          Python ecosystem already uses urllib3 and you should too.
│ │          urllib3 brings many critical features that are missing from the Python
│ │          standard libraries:
│ │          
│ │          - Thread safety.
│ │          - Connection pooling.
│ │          - Client-side SSL/TLS verification.
│ │          - File uploads with multipart encoding.
│ │          - Helpers for retrying requests and dealing with HTTP redirects.
│ │ -        - Support for gzip and deflate encoding.
│ │ +        - Support for gzip, deflate, and brotli encoding.
│ │          - Proxy support for HTTP and SOCKS.
│ │          - 100% test coverage.
│ │          
│ │          urllib3 is powerful and easy to use::
│ │          
│ │              >>> import urllib3
│ │              >>> http = urllib3.PoolManager()
│ │ @@ -85,50 +85,143 @@
│ │          ------------
│ │          
│ │          urllib3 happily accepts contributions. Please see our
│ │          `contributing documentation <https://urllib3.readthedocs.io/en/latest/contributing.html>`_
│ │          for some tips on getting started.
│ │          
│ │          
│ │ +        Security Disclosures
│ │ +        --------------------
│ │ +        
│ │ +        To report a security vulnerability, please use the
│ │ +        `Tidelift security contact <https://tidelift.com/security>`_.
│ │ +        Tidelift will coordinate the fix and disclosure with maintainers.
│ │ +        
│ │          Maintainers
│ │          -----------
│ │          
│ │          - `@theacodes <https://github.com/theacodes>`_ (Thea Flowers)
│ │ -        - `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_ (Seth M. Larson)
│ │ -        - `@haikuginger <https://github.com/haikuginger>`_ (Jesse Shapiro)
│ │ +        - `@sethmlarson <https://github.com/sethmlarson>`_ (Seth M. Larson)
│ │ +        - `@haikuginger <https://github.com/haikuginger>`_ (Jess Shapiro)
│ │          - `@lukasa <https://github.com/lukasa>`_ (Cory Benfield)
│ │          - `@sigmavirus24 <https://github.com/sigmavirus24>`_ (Ian Cordasco)
│ │          - `@shazow <https://github.com/shazow>`_ (Andrey Petrov)
│ │          
│ │          👋
│ │          
│ │          
│ │          Sponsorship
│ │          -----------
│ │          
│ │ +        .. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
│ │ +           :width: 75
│ │ +           :alt: Tidelift
│ │ +        
│ │ +        .. list-table::
│ │ +           :widths: 10 100
│ │ +        
│ │ +           * - |tideliftlogo|
│ │ +             - Professional support for urllib3 is available as part of the `Tidelift
│ │ +               Subscription`_.  Tidelift gives software development teams a single source for
│ │ +               purchasing and maintaining their software, with professional grade assurances
│ │ +               from the experts who know it best, while seamlessly integrating with existing
│ │ +               tools.
│ │ +        
│ │ +        .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme
│ │ +        
│ │          If your company benefits from this library, please consider `sponsoring its
│ │ -        development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship>`_.
│ │ +        development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship-project-grants>`_.
│ │          
│ │          Sponsors include:
│ │          
│ │          - Google Cloud Platform (2018-present), sponsors `@theacodes <https://github.com/theacodes>`_'s work on an ongoing basis
│ │ -        - Abbott (2018-present), sponsors `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_'s work on an ongoing basis
│ │ -        - Akamai (2017-present), sponsors `@haikuginger <https://github.com/haikuginger>`_'s work on an ongoing basis
│ │ +        - Abbott (2018-present), sponsors `@sethmlarson <https://github.com/sethmlarson>`_'s work on an ongoing basis
│ │ +        - Akamai (2017-2018), sponsored `@haikuginger <https://github.com/haikuginger>`_'s work on urllib3
│ │          - Hewlett Packard Enterprise (2016-2017), sponsored `@Lukasa’s <https://github.com/Lukasa>`_ work on urllib3
│ │          
│ │          
│ │          Changes
│ │          =======
│ │          
│ │ +        1.25.3 (2019-05-23)
│ │ +        -------------------
│ │ +        
│ │ +        * Change ``HTTPSConnection`` to load system CA certificates
│ │ +          when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ +          unspecified. (Pull #1608, Issue #1603)
│ │ +        
│ │ +        * Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +        
│ │ +        
│ │ +        1.25.2 (2019-04-28)
│ │ +        -------------------
│ │ +        
│ │ +        * Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +        
│ │ +        * Change ``parse_url`` to percent-encode invalid characters within the
│ │ +          path, query, and target components. (Pull #1586)
│ │ +        
│ │ +        
│ │ +        1.25.1 (2019-04-24)
│ │ +        -------------------
│ │ +        
│ │ +        * Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +        
│ │ +        * Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +        
│ │ +        
│ │ +        1.25 (2019-04-22)
│ │ +        -----------------
│ │ +        
│ │ +        * Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +        
│ │ +        * Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +        
│ │ +        * Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ +          encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +        
│ │ +        * Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ +          implementations. (Pull #1496)
│ │ +        
│ │ +        * Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +        
│ │ +        * Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ +          given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +        
│ │ +        * Added support for Brotli content encoding. It is enabled automatically if
│ │ +          ``brotlipy`` package is installed which can be requested with
│ │ +          ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +        
│ │ +        * Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ +          Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +        
│ │ +        * Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +        
│ │ +        1.24.3 (2019-05-01)
│ │ +        -------------------
│ │ +        
│ │ +        * Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +        
│ │ +        1.24.2 (2019-04-17)
│ │ +        -------------------
│ │ +        
│ │ +        * Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ +          ``ssl_context`` parameters are specified.
│ │ +        
│ │ +        * Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +        
│ │ +        * Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +        
│ │ +        
│ │          1.24.1 (2018-11-02)
│ │          -------------------
│ │          
│ │          * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │          
│ │ -        * Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ +        * Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │          
│ │          
│ │          1.24 (2018-10-16)
│ │          -----------------
│ │          
│ │          * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│ │          
│ │ @@ -1088,14 +1181,17 @@
│ │  Classifier: Programming Language :: Python
│ │  Classifier: Programming Language :: Python :: 2
│ │  Classifier: Programming Language :: Python :: 2.7
│ │  Classifier: Programming Language :: Python :: 3
│ │  Classifier: Programming Language :: Python :: 3.4
│ │  Classifier: Programming Language :: Python :: 3.5
│ │  Classifier: Programming Language :: Python :: 3.6
│ │ +Classifier: Programming Language :: Python :: 3.7
│ │ +Classifier: Programming Language :: Python :: 3.8
│ │  Classifier: Programming Language :: Python :: Implementation :: CPython
│ │  Classifier: Programming Language :: Python :: Implementation :: PyPy
│ │  Classifier: Topic :: Internet :: WWW/HTTP
│ │  Classifier: Topic :: Software Development :: Libraries
│ │  Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4
│ │  Provides-Extra: socks
│ │  Provides-Extra: secure
│ │ +Provides-Extra: brotli
│   --- urllib3-1.24.1/test/test_no_ssl.py
├── +++ urllib3-1.25.3/test/test_no_ssl.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/appengine/conftest.py
├── +++ urllib3-1.25.3/test/appengine/conftest.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/server.csr
├── +++ urllib3-1.25.3/dummyserver/certs/server.csr
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/with_dummyserver/test_proxy_poolmanager.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_proxy_poolmanager.py
│┄ Files similar despite different names (difference score: 19)
│ │ @@ -24,15 +24,15 @@
│ │                                                self.http_port)
│ │          self.https_url = 'https://%s:%d' % (self.https_host, self.https_port)
│ │          self.https_url_alt = 'https://%s:%d' % (self.https_host_alt,
│ │                                                  self.https_port)
│ │          self.proxy_url = 'http://%s:%d' % (self.proxy_host, self.proxy_port)
│ │  
│ │      def test_basic_proxy(self):
│ │ -        http = proxy_from_url(self.proxy_url)
│ │ +        http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/' % self.http_url)
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          r = http.request('GET', '%s/' % self.https_url)
│ │          self.assertEqual(r.status, 200)
│ │ @@ -62,15 +62,15 @@
│ │          try:
│ │              http.request('GET', '%s/' % self.http_url)
│ │              self.fail("Failed to raise retry error.")
│ │          except MaxRetryError as e:
│ │              self.assertEqual(type(e.reason), ProxyError)
│ │  
│ │      def test_oldapi(self):
│ │ -        http = ProxyManager(connection_from_url(self.proxy_url))
│ │ +        http = ProxyManager(connection_from_url(self.proxy_url), ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/' % self.http_url)
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          r = http.request('GET', '%s/' % self.https_url)
│ │          self.assertEqual(r.status, 200)
│ │ @@ -142,15 +142,15 @@
│ │  
│ │          r = http.request('GET', '%s/redirect' % self.http_url,
│ │                           fields={'target': '%s/echo?a=b' % self.http_url_alt},
│ │                           timeout=1, retries=1)
│ │          self.assertNotEqual(r._pool.host, self.http_host_alt)
│ │  
│ │      def test_cross_protocol_redirect(self):
│ │ -        http = proxy_from_url(self.proxy_url)
│ │ +        http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          cross_protocol_location = '%s/echo?a=b' % self.https_url
│ │          try:
│ │              http.request('GET', '%s/redirect' % self.http_url,
│ │                           fields={'target': cross_protocol_location},
│ │                           timeout=1, retries=0)
│ │ @@ -162,15 +162,16 @@
│ │          r = http.request('GET', '%s/redirect' % self.http_url,
│ │                           fields={'target': '%s/echo?a=b' % self.https_url},
│ │                           timeout=1, retries=1)
│ │          self.assertEqual(r._pool.host, self.https_host)
│ │  
│ │      def test_headers(self):
│ │          http = proxy_from_url(self.proxy_url, headers={'Foo': 'bar'},
│ │ -                              proxy_headers={'Hickory': 'dickory'})
│ │ +                              proxy_headers={'Hickory': 'dickory'},
│ │ +                              ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request_encode_url('GET', '%s/headers' % self.http_url)
│ │          returned_headers = json.loads(r.data.decode())
│ │          self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │          self.assertEqual(returned_headers.get('Hickory'), 'dickory')
│ │          self.assertEqual(returned_headers.get('Host'),
│ │ @@ -186,21 +187,14 @@
│ │          r = http.request_encode_url('GET', '%s/headers' % self.https_url)
│ │          returned_headers = json.loads(r.data.decode())
│ │          self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │          self.assertIsNone(returned_headers.get('Hickory'))
│ │          self.assertEqual(returned_headers.get('Host'),
│ │                           '%s:%s' % (self.https_host, self.https_port))
│ │  
│ │ -        r = http.request_encode_url('GET', '%s/headers' % self.https_url_alt)
│ │ -        returned_headers = json.loads(r.data.decode())
│ │ -        self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ -        self.assertIsNone(returned_headers.get('Hickory'))
│ │ -        self.assertEqual(returned_headers.get('Host'),
│ │ -                         '%s:%s' % (self.https_host_alt, self.https_port))
│ │ -
│ │          r = http.request_encode_body('POST', '%s/headers' % self.http_url)
│ │          returned_headers = json.loads(r.data.decode())
│ │          self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │          self.assertEqual(returned_headers.get('Hickory'), 'dickory')
│ │          self.assertEqual(returned_headers.get('Host'),
│ │                           '%s:%s' % (self.http_host, self.http_port))
│ │  
│ │ @@ -250,15 +244,15 @@
│ │          request_headers = HTTPHeaderDict(baz='quux')
│ │          r = http.request('GET', '%s/headers' % self.http_url, headers=request_headers)
│ │          returned_headers = json.loads(r.data.decode())
│ │          self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │          self.assertEqual(returned_headers.get('Baz'), 'quux')
│ │  
│ │      def test_proxy_pooling(self):
│ │ -        http = proxy_from_url(self.proxy_url)
│ │ +        http = proxy_from_url(self.proxy_url, cert_reqs='NONE')
│ │          self.addCleanup(http.clear)
│ │  
│ │          for x in range(2):
│ │              http.urlopen('GET', self.http_url)
│ │          self.assertEqual(len(http.pools), 1)
│ │  
│ │          for x in range(2):
│ │ @@ -316,15 +310,15 @@
│ │              https.request('GET', self.http_url)
│ │              self.fail("Failed to raise retry error.")
│ │          except MaxRetryError as e:
│ │              self.assertEqual(type(e.reason), ConnectTimeoutError)
│ │  
│ │      def test_scheme_host_case_insensitive(self):
│ │          """Assert that upper-case schemes and hosts are normalized."""
│ │ -        http = proxy_from_url(self.proxy_url.upper())
│ │ +        http = proxy_from_url(self.proxy_url.upper(), ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/' % self.http_url.upper())
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          r = http.request('GET', '%s/' % self.https_url.upper())
│ │          self.assertEqual(r.status, 200)
│ │ @@ -338,15 +332,15 @@
│ │                                                self.http_port)
│ │          self.https_url = 'https://%s:%d' % (self.https_host, self.https_port)
│ │          self.https_url_alt = 'https://%s:%d' % (self.https_host_alt,
│ │                                                  self.https_port)
│ │          self.proxy_url = 'http://[%s]:%d' % (self.proxy_host, self.proxy_port)
│ │  
│ │      def test_basic_ipv6_proxy(self):
│ │ -        http = proxy_from_url(self.proxy_url)
│ │ +        http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │          self.addCleanup(http.clear)
│ │  
│ │          r = http.request('GET', '%s/' % self.http_url)
│ │          self.assertEqual(r.status, 200)
│ │  
│ │          r = http.request('GET', '%s/' % self.https_url)
│ │          self.assertEqual(r.status, 200)
│   --- urllib3-1.24.1/src/urllib3/contrib/ntlmpool.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/ntlmpool.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/dummyserver/certs/client_intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/contrib/_securetransport/bindings.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_securetransport/bindings.py
│┄ Files similar despite different names (difference score: 8)
│ │ @@ -512,14 +512,16 @@
│ │      kSSLSessionOptionBreakOnServerAuth = 0
│ │  
│ │      kSSLProtocol2 = 1
│ │      kSSLProtocol3 = 2
│ │      kTLSProtocol1 = 4
│ │      kTLSProtocol11 = 7
│ │      kTLSProtocol12 = 8
│ │ +    kTLSProtocol13 = 10
│ │ +    kTLSProtocolMaxSupported = 999
│ │  
│ │      kSSLClientSide = 1
│ │      kSSLStreamType = 0
│ │  
│ │      kSecFormatPEMSequence = 10
│ │  
│ │      kSecTrustResultInvalid = 0
│ │ @@ -554,40 +556,38 @@
│ │  
│ │      errSecVerifyFailed = -67808
│ │      errSecNoTrustSettings = -25263
│ │      errSecItemNotFound = -25300
│ │      errSecInvalidTrustSettings = -25262
│ │  
│ │      # Cipher suites. We only pick the ones our default cipher string allows.
│ │ +    # Source: https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values
│ │      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C
│ │      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030
│ │      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B
│ │      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F
│ │ -    TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3
│ │ +    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9
│ │ +    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8
│ │      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F
│ │ -    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2
│ │      TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
│ │      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024
│ │      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028
│ │      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A
│ │      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014
│ │      TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
│ │ -    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A
│ │      TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
│ │ -    TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038
│ │      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023
│ │      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027
│ │      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009
│ │      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013
│ │      TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
│ │ -    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040
│ │      TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
│ │ -    TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032
│ │      TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D
│ │      TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
│ │      TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
│ │      TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
│ │      TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
│ │      TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F
│ │      TLS_AES_128_GCM_SHA256 = 0x1301
│ │      TLS_AES_256_GCM_SHA384 = 0x1302
│ │ -    TLS_CHACHA20_POLY1305_SHA256 = 0x1303
│ │ +    TLS_AES_128_CCM_8_SHA256 = 0x1305
│ │ +    TLS_AES_128_CCM_SHA256 = 0x1304
│   --- urllib3-1.24.1/src/urllib3/connection.py
├── +++ urllib3-1.25.3/src/urllib3/connection.py
│┄ Files similar despite different names (difference score: 26)
│ │ @@ -15,18 +15,19 @@
│ │  except (ImportError, AttributeError):  # Platform-specific: No SSL.
│ │      ssl = None
│ │  
│ │      class BaseSSLError(BaseException):
│ │          pass
│ │  
│ │  
│ │ -try:  # Python 3:
│ │ -    # Not a no-op, we're adding this to the namespace so it can be imported.
│ │ +try:
│ │ +    # Python 3: not a no-op, we're adding this to the namespace so it can be imported.
│ │      ConnectionError = ConnectionError
│ │ -except NameError:  # Python 2:
│ │ +except NameError:
│ │ +    # Python 2
│ │      class ConnectionError(Exception):
│ │          pass
│ │  
│ │  
│ │  from .exceptions import (
│ │      NewConnectionError,
│ │      ConnectTimeoutError,
│ │ @@ -97,15 +98,15 @@
│ │      #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]``
│ │      default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]
│ │  
│ │      #: Whether this connection verifies the host's certificate.
│ │      is_verified = False
│ │  
│ │      def __init__(self, *args, **kw):
│ │ -        if six.PY3:  # Python 3
│ │ +        if six.PY3:
│ │              kw.pop('strict', None)
│ │  
│ │          # Pre-set source_address.
│ │          self.source_address = kw.get('source_address')
│ │  
│ │          #: The socket options provided by the user. If no options are
│ │          #: provided, we use the default options.
│ │ @@ -154,28 +155,29 @@
│ │          if self.socket_options:
│ │              extra_kw['socket_options'] = self.socket_options
│ │  
│ │          try:
│ │              conn = connection.create_connection(
│ │                  (self._dns_host, self.port), self.timeout, **extra_kw)
│ │  
│ │ -        except SocketTimeout as e:
│ │ +        except SocketTimeout:
│ │              raise ConnectTimeoutError(
│ │                  self, "Connection to %s timed out. (connect timeout=%s)" %
│ │                  (self.host, self.timeout))
│ │  
│ │          except SocketError as e:
│ │              raise NewConnectionError(
│ │                  self, "Failed to establish a new connection: %s" % e)
│ │  
│ │          return conn
│ │  
│ │      def _prepare_conn(self, conn):
│ │          self.sock = conn
│ │ -        if self._tunnel_host:
│ │ +        # Google App Engine's httplib does not define _tunnel_host
│ │ +        if getattr(self, '_tunnel_host', None):
│ │              # TODO: Fix tunnel so it doesn't depend on self.sock state.
│ │              self._tunnel()
│ │              # Mark this connection as not reusable
│ │              self.auto_open = 0
│ │  
│ │      def connect(self):
│ │          conn = self._new_conn()
│ │ @@ -222,43 +224,57 @@
│ │  
│ │  class HTTPSConnection(HTTPConnection):
│ │      default_port = port_by_scheme['https']
│ │  
│ │      ssl_version = None
│ │  
│ │      def __init__(self, host, port=None, key_file=None, cert_file=None,
│ │ -                 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
│ │ +                 key_password=None, strict=None,
│ │ +                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
│ │                   ssl_context=None, server_hostname=None, **kw):
│ │  
│ │          HTTPConnection.__init__(self, host, port, strict=strict,
│ │                                  timeout=timeout, **kw)
│ │  
│ │          self.key_file = key_file
│ │          self.cert_file = cert_file
│ │ +        self.key_password = key_password
│ │          self.ssl_context = ssl_context
│ │          self.server_hostname = server_hostname
│ │  
│ │          # Required property for Google AppEngine 1.9.0 which otherwise causes
│ │          # HTTPS requests to go out as HTTP. (See Issue #356)
│ │          self._protocol = 'https'
│ │  
│ │      def connect(self):
│ │          conn = self._new_conn()
│ │          self._prepare_conn(conn)
│ │  
│ │ +        # Wrap socket using verification with the root certs in
│ │ +        # trusted_root_certs
│ │ +        default_ssl_context = False
│ │          if self.ssl_context is None:
│ │ +            default_ssl_context = True
│ │              self.ssl_context = create_urllib3_context(
│ │ -                ssl_version=resolve_ssl_version(None),
│ │ -                cert_reqs=resolve_cert_reqs(None),
│ │ +                ssl_version=resolve_ssl_version(self.ssl_version),
│ │ +                cert_reqs=resolve_cert_reqs(self.cert_reqs),
│ │              )
│ │  
│ │ +        # Try to load OS default certs if none are given.
│ │ +        # Works well on Windows (requires Python3.4+)
│ │ +        context = self.ssl_context
│ │ +        if (not self.ca_certs and not self.ca_cert_dir and default_ssl_context
│ │ +                and hasattr(context, 'load_default_certs')):
│ │ +            context.load_default_certs()
│ │ +
│ │          self.sock = ssl_wrap_socket(
│ │              sock=conn,
│ │              keyfile=self.key_file,
│ │              certfile=self.cert_file,
│ │ +            key_password=self.key_password,
│ │              ssl_context=self.ssl_context,
│ │              server_hostname=self.server_hostname
│ │          )
│ │  
│ │  
│ │  class VerifiedHTTPSConnection(HTTPSConnection):
│ │      """
│ │ @@ -268,44 +284,44 @@
│ │      cert_reqs = None
│ │      ca_certs = None
│ │      ca_cert_dir = None
│ │      ssl_version = None
│ │      assert_fingerprint = None
│ │  
│ │      def set_cert(self, key_file=None, cert_file=None,
│ │ -                 cert_reqs=None, ca_certs=None,
│ │ +                 cert_reqs=None, key_password=None, ca_certs=None,
│ │                   assert_hostname=None, assert_fingerprint=None,
│ │                   ca_cert_dir=None):
│ │          """
│ │          This method should only be called once, before the connection is used.
│ │          """
│ │ -        # If cert_reqs is not provided, we can try to guess. If the user gave
│ │ -        # us a cert database, we assume they want to use it: otherwise, if
│ │ -        # they gave us an SSL Context object we should use whatever is set for
│ │ -        # it.
│ │ +        # If cert_reqs is not provided we'll assume CERT_REQUIRED unless we also
│ │ +        # have an SSLContext object in which case we'll use its verify_mode.
│ │          if cert_reqs is None:
│ │ -            if ca_certs or ca_cert_dir:
│ │ -                cert_reqs = 'CERT_REQUIRED'
│ │ -            elif self.ssl_context is not None:
│ │ +            if self.ssl_context is not None:
│ │                  cert_reqs = self.ssl_context.verify_mode
│ │ +            else:
│ │ +                cert_reqs = resolve_cert_reqs(None)
│ │  
│ │          self.key_file = key_file
│ │          self.cert_file = cert_file
│ │          self.cert_reqs = cert_reqs
│ │ +        self.key_password = key_password
│ │          self.assert_hostname = assert_hostname
│ │          self.assert_fingerprint = assert_fingerprint
│ │          self.ca_certs = ca_certs and os.path.expanduser(ca_certs)
│ │          self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir)
│ │  
│ │      def connect(self):
│ │          # Add certificate verification
│ │          conn = self._new_conn()
│ │          hostname = self.host
│ │  
│ │ -        if self._tunnel_host:
│ │ +        # Google App Engine's httplib does not define _tunnel_host
│ │ +        if getattr(self, '_tunnel_host', None):
│ │              self.sock = conn
│ │              # Calls self._set_hostport(), so self.host is
│ │              # self._tunnel_host below.
│ │              self._tunnel()
│ │              # Mark this connection as not reusable
│ │              self.auto_open = 0
│ │  
│ │ @@ -322,26 +338,36 @@
│ │                  'System time is way off (before {0}). This will probably '
│ │                  'lead to SSL verification errors').format(RECENT_DATE),
│ │                  SystemTimeWarning
│ │              )
│ │  
│ │          # Wrap socket using verification with the root certs in
│ │          # trusted_root_certs
│ │ +        default_ssl_context = False
│ │          if self.ssl_context is None:
│ │ +            default_ssl_context = True
│ │              self.ssl_context = create_urllib3_context(
│ │                  ssl_version=resolve_ssl_version(self.ssl_version),
│ │                  cert_reqs=resolve_cert_reqs(self.cert_reqs),
│ │              )
│ │  
│ │          context = self.ssl_context
│ │          context.verify_mode = resolve_cert_reqs(self.cert_reqs)
│ │ +
│ │ +        # Try to load OS default certs if none are given.
│ │ +        # Works well on Windows (requires Python3.4+)
│ │ +        if (not self.ca_certs and not self.ca_cert_dir and default_ssl_context
│ │ +                and hasattr(context, 'load_default_certs')):
│ │ +            context.load_default_certs()
│ │ +
│ │          self.sock = ssl_wrap_socket(
│ │              sock=conn,
│ │              keyfile=self.key_file,
│ │              certfile=self.cert_file,
│ │ +            key_password=self.key_password,
│ │              ca_certs=self.ca_certs,
│ │              ca_cert_dir=self.ca_cert_dir,
│ │              server_hostname=server_hostname,
│ │              ssl_context=context)
│ │  
│ │          if self.assert_fingerprint:
│ │              assert_fingerprint(self.sock.getpeercert(binary_form=True),
│   --- urllib3-1.24.1/dummyserver/certs/server.no_san.csr
├── +++ urllib3-1.25.3/dummyserver/certs/server.no_san.csr
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/Makefile
├── +++ urllib3-1.25.3/Makefile
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/appengine/test_urlfetch.py
├── +++ urllib3-1.25.3/test/appengine/test_urlfetch.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/CONTRIBUTORS.txt
├── +++ urllib3-1.25.3/CONTRIBUTORS.txt
│┄ Files similar despite different names (difference score: 13)
│ │ @@ -189,15 +189,15 @@
│ │  
│ │  * Ville Skyttä <[email protected]>
│ │    * Logging efficiency improvements, spelling fixes, Travis config.
│ │  
│ │  * Shige Takeda <[email protected]>
│ │    * Started Recipes documentation and added a recipe about handling concatenated gzip data in HTTP response
│ │  
│ │ -* Jesse Shapiro <[email protected]>
│ │ +* Jess Shapiro <[email protected]>
│ │    * Various character-encoding fixes/tweaks
│ │    * Disabling IPv6 DNS when IPv6 connections not supported
│ │  
│ │  * David Foster <http://dafoster.net/>
│ │    * Ensure order of request and response headers are preserved.
│ │  
│ │  * Jeremy Cline <[email protected]>
│ │ @@ -240,16 +240,16 @@
│ │  * Mike Miller <[email protected]>
│ │    * Logging improvements to include the HTTP(S) port when opening a new connection
│ │  
│ │  * Ioannis Tziakos <[email protected]>
│ │    * Fix ``util.selectors._fileobj_to_fd`` to accept ``long``.
│ │    * Update appveyor tox setup to use the 64bit python.
│ │  
│ │ -* Akamai (through Jesse Shapiro) <[email protected]>
│ │ -  * Ongoing maintenance
│ │ +* Akamai (through Jess Shapiro) <[email protected]>
│ │ +  * Ongoing maintenance; 2017-2018
│ │  
│ │  * Dominique Leuenberger <[email protected]>
│ │    * Minor fixes in the test suite
│ │  
│ │  * Will Bond <[email protected]>
│ │    * Add Python 2.6 support to ``contrib.securetransport``
│ │  
│ │ @@ -268,9 +268,12 @@
│ │  
│ │  * Tim Bell <https://github.com/timb07>
│ │    * Bugfix for responses with Content-Type: message/* logging warnings
│ │  
│ │  * Justin Bramley <https://github.com/jbramleycl>
│ │    * Add ability to handle multiple Content-Encodings
│ │  
│ │ +* Katsuhiko YOSHIDA <https://github.com/kyoshidajp>
│ │ +  * Remove Authorization header regardless of case when redirecting to cross-site
│ │ +
│ │  * [Your name or handle] <[email or website]>
│ │    * [Brief summary of your changes]
│   --- urllib3-1.24.1/dummyserver/certs/cacert.no_san.pem
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.no_san.pem
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/filepost.py
├── +++ urllib3-1.25.3/src/urllib3/filepost.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/util/response.py
├── +++ urllib3-1.25.3/src/urllib3/util/response.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/with_dummyserver/test_chunked_transfer.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_chunked_transfer.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/src/urllib3/request.py
├── +++ urllib3-1.25.3/src/urllib3/request.py
│┄ Files similar despite different names (difference score: 0)
│   --- urllib3-1.24.1/test/contrib/test_pyopenssl_dependencies.py
├── +++ urllib3-1.25.3/test/contrib/test_pyopenssl_dependencies.py
│┄ Files similar despite different names (difference score: 33)
│ │ @@ -11,19 +11,28 @@
│ │      )
│ │  except ImportError:
│ │      pass
│ │  
│ │  
│ │  def setup_module():
│ │      try:
│ │ -        from urllib3.contrib.pyopenssl import inject_into_urllib3  # noqa: F401
│ │ +        from urllib3.contrib.pyopenssl import inject_into_urllib3
│ │ +        inject_into_urllib3()
│ │      except ImportError as e:
│ │          pytest.skip('Could not import PyOpenSSL: %r' % e)
│ │  
│ │  
│ │ +def teardown_module():
│ │ +    try:
│ │ +        from urllib3.contrib.pyopenssl import extract_from_urllib3
│ │ +        extract_from_urllib3()
│ │ +    except ImportError:
│ │ +        pass
│ │ +
│ │ +
│ │  class TestPyOpenSSLInjection(unittest.TestCase):
│ │      """
│ │      Tests for error handling in pyopenssl's 'inject_into urllib3'
│ │      """
│ │      def test_inject_validate_fail_cryptography(self):
│ │          """
│ │          Injection should not be supported if cryptography is too old.
│   --- urllib3-1.24.1/dummyserver/certs/cacert.pem
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.pem
│┄ Files similar despite different names (difference score: 0)
Clone this wiki locally