urllib3 1.24.1 to 1.25.3 - freedomofpress/securedrop-builder GitHub Wiki

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)
โš ๏ธ **GitHub.com Fallback** โš ๏ธ