diff --git a/396afb118e9a74952ffec21675aff456e10b6579.patch b/396afb118e9a74952ffec21675aff456e10b6579.patch new file mode 100644 index 0000000000000000000000000000000000000000..0102e2f986c6e88fdf1c1b3c95770e99721092de --- /dev/null +++ b/396afb118e9a74952ffec21675aff456e10b6579.patch @@ -0,0 +1,4868 @@ +diff --git a/news/certifi.vendor.rst b/news/certifi.vendor.rst +new file mode 100644 +index 0000000000..b181bc30c4 +--- /dev/null ++++ b/news/certifi.vendor.rst +@@ -0,0 +1 @@ ++Upgrade certifi to 2020.11.8 +diff --git a/news/colorama.vendor.rst b/news/colorama.vendor.rst +new file mode 100644 +index 0000000000..30c755eb04 +--- /dev/null ++++ b/news/colorama.vendor.rst +@@ -0,0 +1 @@ ++Upgrade colorama to 0.4.4 +diff --git a/news/pep517.vendor.rst b/news/pep517.vendor.rst +new file mode 100644 +index 0000000000..945f1e7468 +--- /dev/null ++++ b/news/pep517.vendor.rst +@@ -0,0 +1 @@ ++Upgrade pep517 to 0.9.1 +diff --git a/news/requests.vendor.rst b/news/requests.vendor.rst +new file mode 100644 +index 0000000000..515ca25a94 +--- /dev/null ++++ b/news/requests.vendor.rst +@@ -0,0 +1 @@ ++Upgrade requests to 2.25.0 +diff --git a/news/resolvelib.vendor.rst b/news/resolvelib.vendor.rst +new file mode 100644 +index 0000000000..97e4f4a8e5 +--- /dev/null ++++ b/news/resolvelib.vendor.rst +@@ -0,0 +1 @@ ++Upgrade resolvelib to 0.5.2 +diff --git a/news/toml.vendor.rst b/news/toml.vendor.rst +new file mode 100644 +index 0000000000..566c104f80 +--- /dev/null ++++ b/news/toml.vendor.rst +@@ -0,0 +1 @@ ++Upgrade toml to 0.10.2 +diff --git a/news/urllib3.vendor.rst b/news/urllib3.vendor.rst +new file mode 100644 +index 0000000000..10e1e7b45f +--- /dev/null ++++ b/news/urllib3.vendor.rst +@@ -0,0 +1 @@ ++Upgrade urllib3 to 1.26.2 +diff --git a/noxfile.py b/noxfile.py +index 93a3b24d86..c21abc2a38 100644 +--- a/noxfile.py ++++ b/noxfile.py +@@ -8,6 +8,7 @@ + import os + import shutil + import sys ++from pathlib import Path + + import nox + +@@ -152,9 +153,50 @@ def lint(session): + + @nox.session + def vendoring(session): +- session.install("vendoring") +- +- session.run("vendoring", "sync", ".", "-v") ++ session.install("vendoring>=0.3.0") ++ ++ if "--upgrade" not in session.posargs: ++ session.run("vendoring", "sync", ".", "-v") ++ return ++ ++ def pinned_requirements(path): ++ for line in path.read_text().splitlines(): ++ one, two = line.split("==", 1) ++ name = one.strip() ++ version = two.split("#")[0].strip() ++ yield name, version ++ ++ vendor_txt = Path("src/pip/_vendor/vendor.txt") ++ for name, old_version in pinned_requirements(vendor_txt): ++ # update requirements.txt ++ session.run("vendoring", "update", ".", name) ++ ++ # get the updated version ++ new_version = old_version ++ for inner_name, inner_version in pinned_requirements(vendor_txt): ++ if inner_name == name: ++ # this is a dedicated assignment, to make flake8 happy ++ new_version = inner_version ++ break ++ else: ++ session.error(f"Could not find {name} in {vendor_txt}") ++ ++ # check if the version changed. ++ if new_version == old_version: ++ continue # no change, nothing more to do here. ++ ++ # synchronize the contents ++ session.run("vendoring", "sync", ".") ++ ++ # Determine the correct message ++ message = f"Upgrade {name} to {new_version}" ++ ++ # Write our news fragment ++ news_file = Path("news") / (name + ".vendor.rst") ++ news_file.write_text(message + "\n") # "\n" appeases end-of-line-fixer ++ ++ # Commit the changes ++ release.commit_file(session, ".", message=message) + + + # ----------------------------------------------------------------------------- +diff --git a/src/pip/_vendor/certifi/__init__.py b/src/pip/_vendor/certifi/__init__.py +index 5d52a62e7f..4e5133b261 100644 +--- a/src/pip/_vendor/certifi/__init__.py ++++ b/src/pip/_vendor/certifi/__init__.py +@@ -1,3 +1,3 @@ + from .core import contents, where + +-__version__ = "2020.06.20" ++__version__ = "2020.11.08" +diff --git a/src/pip/_vendor/certifi/cacert.pem b/src/pip/_vendor/certifi/cacert.pem +index 0fd855f464..a1072085ce 100644 +--- a/src/pip/_vendor/certifi/cacert.pem ++++ b/src/pip/_vendor/certifi/cacert.pem +@@ -575,46 +575,6 @@ VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY + WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= + -----END CERTIFICATE----- + +-# Issuer: O=Government Root Certification Authority +-# Subject: O=Government Root Certification Authority +-# Label: "Taiwan GRCA" +-# Serial: 42023070807708724159991140556527066870 +-# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +-# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +-# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +------BEGIN CERTIFICATE----- +-MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +-MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +-YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +-PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +-Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +-AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +-IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +-gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +-yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +-F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +-jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +-ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +-VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +-YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +-EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +-Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +-DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +-MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +-UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +-TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +-qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +-ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +-JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +-hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +-EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +-nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +-udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +-ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +-LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +-pYYsfPQS +------END CERTIFICATE----- +- + # Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com + # Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com + # Label: "DigiCert Assured ID Root CA" +@@ -1062,38 +1022,6 @@ fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv + GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= + -----END CERTIFICATE----- + +-# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +-# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +-# Label: "OISTE WISeKey Global Root GA CA" +-# Serial: 86718877871133159090080555911823548314 +-# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +-# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +-# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +------BEGIN CERTIFICATE----- +-MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +-ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +-aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +-ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +-NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +-A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +-VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +-SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +-MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +-VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +-w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +-mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +-4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +-4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +-DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +-EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +-SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +-ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +-vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +-hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +-Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +-/L7fCg0= +------END CERTIFICATE----- +- + # Issuer: CN=Certigna O=Dhimyotis + # Subject: CN=Certigna O=Dhimyotis + # Label: "Certigna" +@@ -2285,38 +2213,6 @@ e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p + TpPDpFQUWw== + -----END CERTIFICATE----- + +-# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +-# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +-# Label: "EE Certification Centre Root CA" +-# Serial: 112324828676200291871926431888494945866 +-# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +-# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +-# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +------BEGIN CERTIFICATE----- +-MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +-MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +-czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +-CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +-MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +-ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +-b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +-AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +-euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +-bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +-WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +-MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +-1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +-VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +-zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +-BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +-BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +-v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +-E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +-uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +-iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +-GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +------END CERTIFICATE----- +- + # Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH + # Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH + # Label: "D-TRUST Root Class 3 CA 2 2009" +@@ -4618,3 +4514,93 @@ PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE + 1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX + QRBdJ3NghVdJIgc= + -----END CERTIFICATE----- ++ ++# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. ++# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. ++# Label: "Trustwave Global Certification Authority" ++# Serial: 1846098327275375458322922162 ++# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e ++# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5 ++# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8 ++-----BEGIN CERTIFICATE----- ++MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw ++CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x ++ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 ++c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx ++OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI ++SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI ++b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp ++Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ++ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn ++swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu ++7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 ++1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW ++80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP ++JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l ++RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw ++hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 ++coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc ++BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n ++twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud ++EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud ++DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W ++0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe ++uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q ++lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB ++aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE ++sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT ++MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe ++qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh ++VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 ++h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 ++EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK ++yeC2nOnOcXHebD8WpHk= ++-----END CERTIFICATE----- ++ ++# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. ++# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. ++# Label: "Trustwave Global ECC P256 Certification Authority" ++# Serial: 4151900041497450638097112925 ++# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54 ++# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf ++# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4 ++-----BEGIN CERTIFICATE----- ++MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD ++VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf ++BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 ++YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x ++NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G ++A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 ++d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF ++Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG ++SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN ++FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w ++DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw ++CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh ++DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 ++-----END CERTIFICATE----- ++ ++# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. ++# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. ++# Label: "Trustwave Global ECC P384 Certification Authority" ++# Serial: 2704997926503831671788816187 ++# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6 ++# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2 ++# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97 ++-----BEGIN CERTIFICATE----- ++MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD ++VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf ++BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 ++YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x ++NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G ++A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 ++d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF ++Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ ++j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF ++1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G ++A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 ++AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC ++MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu ++Sw== ++-----END CERTIFICATE----- +diff --git a/src/pip/_vendor/colorama/__init__.py b/src/pip/_vendor/colorama/__init__.py +index 34c263cc8b..b149ed79b0 100644 +--- a/src/pip/_vendor/colorama/__init__.py ++++ b/src/pip/_vendor/colorama/__init__.py +@@ -3,4 +3,4 @@ + from .ansi import Fore, Back, Style, Cursor + from .ansitowin32 import AnsiToWin32 + +-__version__ = '0.4.3' ++__version__ = '0.4.4' +diff --git a/src/pip/_vendor/colorama/ansi.py b/src/pip/_vendor/colorama/ansi.py +index 78776588db..11ec695ff7 100644 +--- a/src/pip/_vendor/colorama/ansi.py ++++ b/src/pip/_vendor/colorama/ansi.py +@@ -6,7 +6,7 @@ + + CSI = '\033[' + OSC = '\033]' +-BEL = '\007' ++BEL = '\a' + + + def code_to_chars(code): +diff --git a/src/pip/_vendor/colorama/ansitowin32.py b/src/pip/_vendor/colorama/ansitowin32.py +index 359c92be50..6039a05432 100644 +--- a/src/pip/_vendor/colorama/ansitowin32.py ++++ b/src/pip/_vendor/colorama/ansitowin32.py +@@ -3,7 +3,7 @@ + import sys + import os + +-from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style ++from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL + from .winterm import WinTerm, WinColor, WinStyle + from .win32 import windll, winapi_test + +@@ -68,7 +68,7 @@ class AnsiToWin32(object): + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer +- ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command ++ ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) +@@ -247,11 +247,12 @@ def convert_osc(self, text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() +- if command in '\x07': # \x07 = BEL +- params = paramstring.split(";") +- # 0 - change title and icon (we will only change title) +- # 1 - change icon (we don't support this) +- # 2 - change title +- if params[0] in '02': +- winterm.set_title(params[1]) ++ if command == BEL: ++ if paramstring.count(";") == 1: ++ params = paramstring.split(";") ++ # 0 - change title and icon (we will only change title) ++ # 1 - change icon (we don't support this) ++ # 2 - change title ++ if params[0] in '02': ++ winterm.set_title(params[1]) + return text +diff --git a/src/pip/_vendor/pep517/__init__.py b/src/pip/_vendor/pep517/__init__.py +index 7355b68a24..10687486e2 100644 +--- a/src/pip/_vendor/pep517/__init__.py ++++ b/src/pip/_vendor/pep517/__init__.py +@@ -1,4 +1,6 @@ + """Wrappers to build Python packages using PEP 517 hooks + """ + +-__version__ = '0.8.2' ++__version__ = '0.9.1' ++ ++from .wrappers import * # noqa: F401, F403 +diff --git a/src/pip/_vendor/pep517/wrappers.py b/src/pip/_vendor/pep517/wrappers.py +index 00a3d1a789..d6338ea520 100644 +--- a/src/pip/_vendor/pep517/wrappers.py ++++ b/src/pip/_vendor/pep517/wrappers.py +@@ -9,6 +9,15 @@ + + from . import compat + ++__all__ = [ ++ 'BackendUnavailable', ++ 'BackendInvalid', ++ 'HookMissing', ++ 'UnsupportedOperation', ++ 'default_subprocess_runner', ++ 'quiet_subprocess_runner', ++ 'Pep517HookCaller', ++] + + try: + import importlib.resources as resources +@@ -102,19 +111,22 @@ def norm_and_check(source_tree, requested): + class Pep517HookCaller(object): + """A wrapper around a source directory to be built with a PEP 517 backend. + +- source_dir : The path to the source directory, containing pyproject.toml. +- build_backend : The build backend spec, as per PEP 517, from ++ :param source_dir: The path to the source directory, containing + pyproject.toml. +- backend_path : The backend path, as per PEP 517, from pyproject.toml. +- runner : A callable that invokes the wrapper subprocess. ++ :param build_backend: The build backend spec, as per PEP 517, from ++ pyproject.toml. ++ :param backend_path: The backend path, as per PEP 517, from pyproject.toml. ++ :param runner: A callable that invokes the wrapper subprocess. ++ :param python_executable: The Python executable used to invoke the backend + + The 'runner', if provided, must expect the following: +- cmd : a list of strings representing the command and arguments to +- execute, as would be passed to e.g. 'subprocess.check_call'. +- cwd : a string representing the working directory that must be +- used for the subprocess. Corresponds to the provided source_dir. +- extra_environ : a dict mapping environment variable names to values +- which must be set for the subprocess execution. ++ ++ - cmd: a list of strings representing the command and arguments to ++ execute, as would be passed to e.g. 'subprocess.check_call'. ++ - cwd: a string representing the working directory that must be ++ used for the subprocess. Corresponds to the provided source_dir. ++ - extra_environ: a dict mapping environment variable names to values ++ which must be set for the subprocess execution. + """ + def __init__( + self, +@@ -122,6 +134,7 @@ def __init__( + build_backend, + backend_path=None, + runner=None, ++ python_executable=None, + ): + if runner is None: + runner = default_subprocess_runner +@@ -134,6 +147,9 @@ def __init__( + ] + self.backend_path = backend_path + self._subprocess_runner = runner ++ if not python_executable: ++ python_executable = sys.executable ++ self.python_executable = python_executable + + @contextmanager + def subprocess_runner(self, runner): +@@ -150,7 +166,8 @@ def subprocess_runner(self, runner): + def get_requires_for_build_wheel(self, config_settings=None): + """Identify packages required for building a wheel + +- Returns a list of dependency specifications, e.g.: ++ Returns a list of dependency specifications, e.g.:: ++ + ["wheel >= 0.25", "setuptools"] + + This does not include requirements specified in pyproject.toml. +@@ -164,7 +181,7 @@ def get_requires_for_build_wheel(self, config_settings=None): + def prepare_metadata_for_build_wheel( + self, metadata_directory, config_settings=None, + _allow_fallback=True): +- """Prepare a *.dist-info folder with metadata for this project. ++ """Prepare a ``*.dist-info`` folder with metadata for this project. + + Returns the name of the newly created folder. + +@@ -202,7 +219,8 @@ def build_wheel( + def get_requires_for_build_sdist(self, config_settings=None): + """Identify packages required for building a wheel + +- Returns a list of dependency specifications, e.g.: ++ Returns a list of dependency specifications, e.g.:: ++ + ["setuptools >= 26"] + + This does not include requirements specified in pyproject.toml. +@@ -252,8 +270,9 @@ def _call_hook(self, hook_name, kwargs): + + # Run the hook in a subprocess + with _in_proc_script_path() as script: ++ python = self.python_executable + self._subprocess_runner( +- [sys.executable, str(script), hook_name, td], ++ [python, abspath(str(script)), hook_name, td], + cwd=self.source_dir, + extra_environ=extra_environ + ) +diff --git a/src/pip/_vendor/requests/LICENSE b/src/pip/_vendor/requests/LICENSE +index 13d91ddc7a..67db858821 100644 +--- a/src/pip/_vendor/requests/LICENSE ++++ b/src/pip/_vendor/requests/LICENSE +@@ -1,13 +1,175 @@ +-Copyright 2019 Kenneth Reitz + +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at ++ Apache License ++ Version 2.0, January 2004 ++ http://www.apache.org/licenses/ + +- https://www.apache.org/licenses/LICENSE-2.0 ++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. ++ 1. Definitions. ++ ++ "License" shall mean the terms and conditions for use, reproduction, ++ and distribution as defined by Sections 1 through 9 of this document. ++ ++ "Licensor" shall mean the copyright owner or entity authorized by ++ the copyright owner that is granting the License. ++ ++ "Legal Entity" shall mean the union of the acting entity and all ++ other entities that control, are controlled by, or are under common ++ control with that entity. For the purposes of this definition, ++ "control" means (i) the power, direct or indirect, to cause the ++ direction or management of such entity, whether by contract or ++ otherwise, or (ii) ownership of fifty percent (50%) or more of the ++ outstanding shares, or (iii) beneficial ownership of such entity. ++ ++ "You" (or "Your") shall mean an individual or Legal Entity ++ exercising permissions granted by this License. ++ ++ "Source" form shall mean the preferred form for making modifications, ++ including but not limited to software source code, documentation ++ source, and configuration files. ++ ++ "Object" form shall mean any form resulting from mechanical ++ transformation or translation of a Source form, including but ++ not limited to compiled object code, generated documentation, ++ and conversions to other media types. ++ ++ "Work" shall mean the work of authorship, whether in Source or ++ Object form, made available under the License, as indicated by a ++ copyright notice that is included in or attached to the work ++ (an example is provided in the Appendix below). ++ ++ "Derivative Works" shall mean any work, whether in Source or Object ++ form, that is based on (or derived from) the Work and for which the ++ editorial revisions, annotations, elaborations, or other modifications ++ represent, as a whole, an original work of authorship. For the purposes ++ of this License, Derivative Works shall not include works that remain ++ separable from, or merely link (or bind by name) to the interfaces of, ++ the Work and Derivative Works thereof. ++ ++ "Contribution" shall mean any work of authorship, including ++ the original version of the Work and any modifications or additions ++ to that Work or Derivative Works thereof, that is intentionally ++ submitted to Licensor for inclusion in the Work by the copyright owner ++ or by an individual or Legal Entity authorized to submit on behalf of ++ the copyright owner. For the purposes of this definition, "submitted" ++ means any form of electronic, verbal, or written communication sent ++ to the Licensor or its representatives, including but not limited to ++ communication on electronic mailing lists, source code control systems, ++ and issue tracking systems that are managed by, or on behalf of, the ++ Licensor for the purpose of discussing and improving the Work, but ++ excluding communication that is conspicuously marked or otherwise ++ designated in writing by the copyright owner as "Not a Contribution." ++ ++ "Contributor" shall mean Licensor and any individual or Legal Entity ++ on behalf of whom a Contribution has been received by Licensor and ++ subsequently incorporated within the Work. ++ ++ 2. Grant of Copyright License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ copyright license to reproduce, prepare Derivative Works of, ++ publicly display, publicly perform, sublicense, and distribute the ++ Work and such Derivative Works in Source or Object form. ++ ++ 3. Grant of Patent License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ (except as stated in this section) patent license to make, have made, ++ use, offer to sell, sell, import, and otherwise transfer the Work, ++ where such license applies only to those patent claims licensable ++ by such Contributor that are necessarily infringed by their ++ Contribution(s) alone or by combination of their Contribution(s) ++ with the Work to which such Contribution(s) was submitted. If You ++ institute patent litigation against any entity (including a ++ cross-claim or counterclaim in a lawsuit) alleging that the Work ++ or a Contribution incorporated within the Work constitutes direct ++ or contributory patent infringement, then any patent licenses ++ granted to You under this License for that Work shall terminate ++ as of the date such litigation is filed. ++ ++ 4. Redistribution. You may reproduce and distribute copies of the ++ Work or Derivative Works thereof in any medium, with or without ++ modifications, and in Source or Object form, provided that You ++ meet the following conditions: ++ ++ (a) You must give any other recipients of the Work or ++ Derivative Works a copy of this License; and ++ ++ (b) You must cause any modified files to carry prominent notices ++ stating that You changed the files; and ++ ++ (c) You must retain, in the Source form of any Derivative Works ++ that You distribute, all copyright, patent, trademark, and ++ attribution notices from the Source form of the Work, ++ excluding those notices that do not pertain to any part of ++ the Derivative Works; and ++ ++ (d) If the Work includes a "NOTICE" text file as part of its ++ distribution, then any Derivative Works that You distribute must ++ include a readable copy of the attribution notices contained ++ within such NOTICE file, excluding those notices that do not ++ pertain to any part of the Derivative Works, in at least one ++ of the following places: within a NOTICE text file distributed ++ as part of the Derivative Works; within the Source form or ++ documentation, if provided along with the Derivative Works; or, ++ within a display generated by the Derivative Works, if and ++ wherever such third-party notices normally appear. The contents ++ of the NOTICE file are for informational purposes only and ++ do not modify the License. You may add Your own attribution ++ notices within Derivative Works that You distribute, alongside ++ or as an addendum to the NOTICE text from the Work, provided ++ that such additional attribution notices cannot be construed ++ as modifying the License. ++ ++ You may add Your own copyright statement to Your modifications and ++ may provide additional or different license terms and conditions ++ for use, reproduction, or distribution of Your modifications, or ++ for any such Derivative Works as a whole, provided Your use, ++ reproduction, and distribution of the Work otherwise complies with ++ the conditions stated in this License. ++ ++ 5. Submission of Contributions. Unless You explicitly state otherwise, ++ any Contribution intentionally submitted for inclusion in the Work ++ by You to the Licensor shall be under the terms and conditions of ++ this License, without any additional terms or conditions. ++ Notwithstanding the above, nothing herein shall supersede or modify ++ the terms of any separate license agreement you may have executed ++ with Licensor regarding such Contributions. ++ ++ 6. Trademarks. This License does not grant permission to use the trade ++ names, trademarks, service marks, or product names of the Licensor, ++ except as required for reasonable and customary use in describing the ++ origin of the Work and reproducing the content of the NOTICE file. ++ ++ 7. Disclaimer of Warranty. Unless required by applicable law or ++ agreed to in writing, Licensor provides the Work (and each ++ Contributor provides its Contributions) on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ implied, including, without limitation, any warranties or conditions ++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A ++ PARTICULAR PURPOSE. You are solely responsible for determining the ++ appropriateness of using or redistributing the Work and assume any ++ risks associated with Your exercise of permissions under this License. ++ ++ 8. Limitation of Liability. In no event and under no legal theory, ++ whether in tort (including negligence), contract, or otherwise, ++ unless required by applicable law (such as deliberate and grossly ++ negligent acts) or agreed to in writing, shall any Contributor be ++ liable to You for damages, including any direct, indirect, special, ++ incidental, or consequential damages of any character arising as a ++ result of this License or out of the use or inability to use the ++ Work (including but not limited to damages for loss of goodwill, ++ work stoppage, computer failure or malfunction, or any and all ++ other commercial damages or losses), even if such Contributor ++ has been advised of the possibility of such damages. ++ ++ 9. Accepting Warranty or Additional Liability. While redistributing ++ the Work or Derivative Works thereof, You may choose to offer, ++ and charge a fee for, acceptance of support, warranty, indemnity, ++ or other liability obligations and/or rights consistent with this ++ License. However, in accepting such obligations, You may act only ++ on Your own behalf and on Your sole responsibility, not on behalf ++ of any other Contributor, and only if You agree to indemnify, ++ defend, and hold each Contributor harmless for any liability ++ incurred by, or claims asserted against, such Contributor by reason ++ of your accepting any such warranty or additional liability. +diff --git a/src/pip/_vendor/requests/__init__.py b/src/pip/_vendor/requests/__init__.py +index 517458b5a2..4bea577a36 100644 +--- a/src/pip/_vendor/requests/__init__.py ++++ b/src/pip/_vendor/requests/__init__.py +@@ -57,10 +57,10 @@ def check_compatibility(urllib3_version, chardet_version): + # Check urllib3 for compatibility. + major, minor, patch = urllib3_version # noqa: F811 + major, minor, patch = int(major), int(minor), int(patch) +- # urllib3 >= 1.21.1, <= 1.25 ++ # urllib3 >= 1.21.1, <= 1.26 + assert major == 1 + assert minor >= 21 +- assert minor <= 25 ++ assert minor <= 26 + + # Check chardet for compatibility. + major, minor, patch = chardet_version.split('.')[:3] +diff --git a/src/pip/_vendor/requests/__version__.py b/src/pip/_vendor/requests/__version__.py +index 531e26ceb2..7108520775 100644 +--- a/src/pip/_vendor/requests/__version__.py ++++ b/src/pip/_vendor/requests/__version__.py +@@ -5,8 +5,8 @@ + __title__ = 'requests' + __description__ = 'Python HTTP for Humans.' + __url__ = 'https://requests.readthedocs.io' +-__version__ = '2.24.0' +-__build__ = 0x022400 ++__version__ = '2.25.0' ++__build__ = 0x022500 + __author__ = 'Kenneth Reitz' + __author_email__ = 'me@kennethreitz.org' + __license__ = 'Apache 2.0' +diff --git a/src/pip/_vendor/requests/models.py b/src/pip/_vendor/requests/models.py +index 015e715dad..b0ce2950f2 100644 +--- a/src/pip/_vendor/requests/models.py ++++ b/src/pip/_vendor/requests/models.py +@@ -273,7 +273,9 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): + """The fully mutable :class:`PreparedRequest ` object, + containing the exact bytes that will be sent to the server. + +- Generated from either a :class:`Request ` object or manually. ++ Instances are generated from a :class:`Request ` object, and ++ should not be instantiated manually; doing so may produce undesirable ++ effects. + + Usage:: + +diff --git a/src/pip/_vendor/requests/sessions.py b/src/pip/_vendor/requests/sessions.py +index e8e2d609a7..fdf7e9fe35 100644 +--- a/src/pip/_vendor/requests/sessions.py ++++ b/src/pip/_vendor/requests/sessions.py +@@ -387,6 +387,13 @@ def __init__(self): + self.stream = False + + #: SSL Verification default. ++ #: Defaults to `True`, requiring requests to verify the TLS certificate at the ++ #: remote end. ++ #: If verify is set to `False`, requests will accept any TLS certificate ++ #: presented by the server, and will ignore hostname mismatches and/or ++ #: expired certificates, which will make your application vulnerable to ++ #: man-in-the-middle (MitM) attacks. ++ #: Only set this to `False` for testing. + self.verify = True + + #: SSL client certificate default, if String, path to ssl client +@@ -495,7 +502,12 @@ def request(self, method, url, + content. Defaults to ``False``. + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path +- to a CA bundle to use. Defaults to ``True``. ++ to a CA bundle to use. Defaults to ``True``. When set to ++ ``False``, requests will accept any TLS certificate presented by ++ the server, and will ignore hostname mismatches and/or expired ++ certificates, which will make your application vulnerable to ++ man-in-the-middle (MitM) attacks. Setting verify to ``False`` ++ may be useful during local development or testing. + :param cert: (optional) if String, path to ssl client cert file (.pem). + If Tuple, ('cert', 'key') pair. + :rtype: requests.Response +diff --git a/src/pip/_vendor/requests/utils.py b/src/pip/_vendor/requests/utils.py +index c1700d7fe8..16d5776201 100644 +--- a/src/pip/_vendor/requests/utils.py ++++ b/src/pip/_vendor/requests/utils.py +@@ -169,14 +169,20 @@ def super_len(o): + def get_netrc_auth(url, raise_errors=False): + """Returns the Requests tuple auth for a given url from netrc.""" + ++ netrc_file = os.environ.get('NETRC') ++ if netrc_file is not None: ++ netrc_locations = (netrc_file,) ++ else: ++ netrc_locations = ('~/{}'.format(f) for f in NETRC_FILES) ++ + try: + from netrc import netrc, NetrcParseError + + netrc_path = None + +- for f in NETRC_FILES: ++ for f in netrc_locations: + try: +- loc = os.path.expanduser('~/{}'.format(f)) ++ loc = os.path.expanduser(f) + except KeyError: + # os.path.expanduser can fail when $HOME is undefined and + # getpwuid fails. See https://bugs.python.org/issue20164 & +@@ -212,7 +218,7 @@ def get_netrc_auth(url, raise_errors=False): + if raise_errors: + raise + +- # AppEngine hackiness. ++ # App Engine hackiness. + except (ImportError, AttributeError): + pass + +diff --git a/src/pip/_vendor/resolvelib/__init__.py b/src/pip/_vendor/resolvelib/__init__.py +index 3b444545de..78ede4fd1a 100644 +--- a/src/pip/_vendor/resolvelib/__init__.py ++++ b/src/pip/_vendor/resolvelib/__init__.py +@@ -11,7 +11,7 @@ + "ResolutionTooDeep", + ] + +-__version__ = "0.4.0" ++__version__ = "0.5.2" + + + from .providers import AbstractProvider, AbstractResolver +diff --git a/src/pip/_vendor/resolvelib/providers.py b/src/pip/_vendor/resolvelib/providers.py +index 68b7290dfa..965cf9c138 100644 +--- a/src/pip/_vendor/resolvelib/providers.py ++++ b/src/pip/_vendor/resolvelib/providers.py +@@ -1,32 +1,36 @@ + class AbstractProvider(object): +- """Delegate class to provide requirement interface for the resolver. +- """ ++ """Delegate class to provide requirement interface for the resolver.""" + +- def identify(self, dependency): +- """Given a dependency, return an identifier for it. ++ def identify(self, requirement_or_candidate): ++ """Given a requirement or candidate, return an identifier for it. + +- This is used in many places to identify the dependency, e.g. whether +- two requirements should have their specifier parts merged, whether +- two specifications would conflict with each other (because they the +- same name but different versions). ++ This is used in many places to identify a requirement or candidate, ++ e.g. whether two requirements should have their specifier parts merged, ++ whether two candidates would conflict with each other (because they ++ have same name but different versions). + """ + raise NotImplementedError + + def get_preference(self, resolution, candidates, information): +- """Produce a sort key for given specification based on preference. ++ """Produce a sort key for given requirement based on preference. + + The preference is defined as "I think this requirement should be + resolved first". The lower the return value is, the more preferred + this group of arguments is. + + :param resolution: Currently pinned candidate, or `None`. +- :param candidates: A list of possible candidates. ++ :param candidates: An iterable of possible candidates. + :param information: A list of requirement information. + +- Each information instance is a named tuple with two entries: ++ The `candidates` iterable's exact type depends on the return type of ++ `find_matches()`. A sequence is passed-in as-is if possible. If it ++ returns a callble, the iterator returned by that callable is passed ++ in here. ++ ++ Each element in `information` is a named tuple with two entries: + + * `requirement` specifies a requirement contributing to the current +- candidate list ++ candidate list. + * `parent` specifies the candidate that provides (dependend on) the + requirement, or `None` to indicate a root requirement. + +@@ -43,7 +47,7 @@ def get_preference(self, resolution, candidates, information): + + A sortable value should be returned (this will be used as the `key` + parameter of the built-in sorting function). The smaller the value is, +- the more preferred this specification is (i.e. the sorting function ++ the more preferred this requirement is (i.e. the sorting function + is called with `reverse=False`). + """ + raise NotImplementedError +@@ -56,11 +60,18 @@ def find_matches(self, requirements): + returned, and for a "named" requirement, the index(es) should be + consulted to find concrete candidates for this requirement. + +- :param requirements: A collection of requirements which all of the the ++ The return value should produce candidates ordered by preference; the ++ most preferred candidate should come first. The return type may be one ++ of the following: ++ ++ * A callable that returns an iterator that yields candidates. ++ * An collection of candidates. ++ * An iterable of candidates. This will be consumed immediately into a ++ list of candidates. ++ ++ :param requirements: A collection of requirements which all of the + returned candidates must match. All requirements are guaranteed to + have the same identifier. The collection is never empty. +- :returns: An iterable that orders candidates by preference, e.g. the +- most preferred candidate should come first. + """ + raise NotImplementedError + +@@ -85,8 +96,7 @@ def get_dependencies(self, candidate): + + + class AbstractResolver(object): +- """The thing that performs the actual resolution work. +- """ ++ """The thing that performs the actual resolution work.""" + + base_exception = Exception + +diff --git a/src/pip/_vendor/resolvelib/reporters.py b/src/pip/_vendor/resolvelib/reporters.py +index a0a2a45884..563489e133 100644 +--- a/src/pip/_vendor/resolvelib/reporters.py ++++ b/src/pip/_vendor/resolvelib/reporters.py +@@ -1,10 +1,8 @@ + class BaseReporter(object): +- """Delegate class to provider progress reporting for the resolver. +- """ ++ """Delegate class to provider progress reporting for the resolver.""" + + def starting(self): +- """Called before the resolution actually starts. +- """ ++ """Called before the resolution actually starts.""" + + def starting_round(self, index): + """Called before each round of resolution starts. +@@ -20,8 +18,7 @@ def ending_round(self, index, state): + """ + + def ending(self, state): +- """Called before the resolution ends successfully. +- """ ++ """Called before the resolution ends successfully.""" + + def adding_requirement(self, requirement, parent): + """Called when adding a new requirement into the resolve criteria. +@@ -34,9 +31,7 @@ def adding_requirement(self, requirement, parent): + """ + + def backtracking(self, candidate): +- """Called when rejecting a candidate during backtracking. +- """ ++ """Called when rejecting a candidate during backtracking.""" + + def pinning(self, candidate): +- """Called when adding a candidate to the potential solution. +- """ ++ """Called when adding a candidate to the potential solution.""" +diff --git a/src/pip/_vendor/resolvelib/resolvers.py b/src/pip/_vendor/resolvelib/resolvers.py +index 4497f976a8..976608b177 100644 +--- a/src/pip/_vendor/resolvelib/resolvers.py ++++ b/src/pip/_vendor/resolvelib/resolvers.py +@@ -1,8 +1,7 @@ + import collections + +-from .compat import collections_abc + from .providers import AbstractResolver +-from .structs import DirectedGraph ++from .structs import DirectedGraph, build_iter_view + + + RequirementInformation = collections.namedtuple( +@@ -76,17 +75,11 @@ def __repr__(self): + + @classmethod + def from_requirement(cls, provider, requirement, parent): +- """Build an instance from a requirement. +- """ +- candidates = provider.find_matches([requirement]) +- if not isinstance(candidates, collections_abc.Sequence): +- candidates = list(candidates) +- criterion = cls( +- candidates=candidates, +- information=[RequirementInformation(requirement, parent)], +- incompatibilities=[], +- ) +- if not candidates: ++ """Build an instance from a requirement.""" ++ cands = build_iter_view(provider.find_matches([requirement])) ++ infos = [RequirementInformation(requirement, parent)] ++ criterion = cls(cands, infos, incompatibilities=[]) ++ if not cands: + raise RequirementsConflicted(criterion) + return criterion + +@@ -97,15 +90,12 @@ def iter_parent(self): + return (i.parent for i in self.information) + + def merged_with(self, provider, requirement, parent): +- """Build a new instance from this and a new requirement. +- """ ++ """Build a new instance from this and a new requirement.""" + infos = list(self.information) + infos.append(RequirementInformation(requirement, parent)) +- candidates = provider.find_matches([r for r, _ in infos]) +- if not isinstance(candidates, collections_abc.Sequence): +- candidates = list(candidates) +- criterion = type(self)(candidates, infos, list(self.incompatibilities)) +- if not candidates: ++ cands = build_iter_view(provider.find_matches([r for r, _ in infos])) ++ criterion = type(self)(cands, infos, list(self.incompatibilities)) ++ if not cands: + raise RequirementsConflicted(criterion) + return criterion + +@@ -114,13 +104,12 @@ def excluded_of(self, candidate): + + Returns the new instance, or None if we still have no valid candidates. + """ ++ cands = self.candidates.excluding(candidate) ++ if not cands: ++ return None + incompats = list(self.incompatibilities) + incompats.append(candidate) +- candidates = [c for c in self.candidates if c != candidate] +- if not candidates: +- return None +- criterion = type(self)(candidates, list(self.information), incompats) +- return criterion ++ return type(self)(cands, list(self.information), incompats) + + + class ResolutionError(ResolverException): +@@ -175,7 +164,8 @@ def _push_new_state(self): + state = State(mapping=collections.OrderedDict(), criteria={}) + else: + state = State( +- mapping=base.mapping.copy(), criteria=base.criteria.copy(), ++ mapping=base.mapping.copy(), ++ criteria=base.criteria.copy(), + ) + self._states.append(state) + +@@ -192,12 +182,10 @@ def _merge_into_criterion(self, requirement, parent): + + def _get_criterion_item_preference(self, item): + name, criterion = item +- try: +- pinned = self.state.mapping[name] +- except KeyError: +- pinned = None + return self._p.get_preference( +- pinned, criterion.candidates, criterion.information, ++ self.state.mapping.get(name), ++ criterion.candidates.for_preference(), ++ criterion.information, + ) + + def _is_current_pin_satisfying(self, name, criterion): +@@ -390,8 +378,7 @@ def _build_result(state): + + + class Resolver(AbstractResolver): +- """The thing that performs the actual resolution work. +- """ ++ """The thing that performs the actual resolution work.""" + + base_exception = ResolverException + +diff --git a/src/pip/_vendor/resolvelib/structs.py b/src/pip/_vendor/resolvelib/structs.py +index 1eee08b383..479aad5dc1 100644 +--- a/src/pip/_vendor/resolvelib/structs.py ++++ b/src/pip/_vendor/resolvelib/structs.py +@@ -1,6 +1,8 @@ ++from .compat import collections_abc ++ ++ + class DirectedGraph(object): +- """A graph structure with directed edges. +- """ ++ """A graph structure with directed edges.""" + + def __init__(self): + self._vertices = set() +@@ -17,8 +19,7 @@ def __contains__(self, key): + return key in self._vertices + + def copy(self): +- """Return a shallow copy of this graph. +- """ ++ """Return a shallow copy of this graph.""" + other = DirectedGraph() + other._vertices = set(self._vertices) + other._forwards = {k: set(v) for k, v in self._forwards.items()} +@@ -26,8 +27,7 @@ def copy(self): + return other + + def add(self, key): +- """Add a new vertex to the graph. +- """ ++ """Add a new vertex to the graph.""" + if key in self._vertices: + raise ValueError("vertex exists") + self._vertices.add(key) +@@ -35,8 +35,7 @@ def add(self, key): + self._backwards[key] = set() + + def remove(self, key): +- """Remove a vertex from the graph, disconnecting all edges from/to it. +- """ ++ """Remove a vertex from the graph, disconnecting all edges from/to it.""" + self._vertices.remove(key) + for f in self._forwards.pop(key): + self._backwards[f].remove(key) +@@ -66,3 +65,79 @@ def iter_children(self, key): + + def iter_parents(self, key): + return iter(self._backwards[key]) ++ ++ ++class _FactoryIterableView(object): ++ """Wrap an iterator factory returned by `find_matches()`. ++ ++ Calling `iter()` on this class would invoke the underlying iterator ++ factory, making it a "collection with ordering" that can be iterated ++ through multiple times, but lacks random access methods presented in ++ built-in Python sequence types. ++ """ ++ ++ def __init__(self, factory): ++ self._factory = factory ++ ++ def __bool__(self): ++ try: ++ next(self._factory()) ++ except StopIteration: ++ return False ++ return True ++ ++ __nonzero__ = __bool__ # XXX: Python 2. ++ ++ def __iter__(self): ++ return self._factory() ++ ++ def for_preference(self): ++ """Provide an candidate iterable for `get_preference()`""" ++ return self._factory() ++ ++ def excluding(self, candidate): ++ """Create a new `Candidates` instance excluding `candidate`.""" ++ ++ def factory(): ++ return (c for c in self._factory() if c != candidate) ++ ++ return type(self)(factory) ++ ++ ++class _SequenceIterableView(object): ++ """Wrap an iterable returned by find_matches(). ++ ++ This is essentially just a proxy to the underlying sequence that provides ++ the same interface as `_FactoryIterableView`. ++ """ ++ ++ def __init__(self, sequence): ++ self._sequence = sequence ++ ++ def __bool__(self): ++ return bool(self._sequence) ++ ++ __nonzero__ = __bool__ # XXX: Python 2. ++ ++ def __iter__(self): ++ return iter(self._sequence) ++ ++ def __len__(self): ++ return len(self._sequence) ++ ++ def for_preference(self): ++ """Provide an candidate iterable for `get_preference()`""" ++ return self._sequence ++ ++ def excluding(self, candidate): ++ """Create a new instance excluding `candidate`.""" ++ return type(self)([c for c in self._sequence if c != candidate]) ++ ++ ++def build_iter_view(matches): ++ """Build an iterable view from the value returned by `find_matches()`.""" ++ if callable(matches): ++ return _FactoryIterableView(matches) ++ if not isinstance(matches, collections_abc.Sequence): ++ matches = list(matches) ++ return _SequenceIterableView(matches) +diff --git a/src/pip/_vendor/toml/__init__.py b/src/pip/_vendor/toml/__init__.py +index 7a08fe7254..34a5eabb6e 100644 +--- a/src/pip/_vendor/toml/__init__.py ++++ b/src/pip/_vendor/toml/__init__.py +@@ -6,7 +6,7 @@ + from pip._vendor.toml import encoder + from pip._vendor.toml import decoder + +-__version__ = "0.10.1" ++__version__ = "0.10.2" + _spec_ = "0.5.0" + + load = decoder.load +diff --git a/src/pip/_vendor/toml/common.py b/src/pip/_vendor/toml/common.py +deleted file mode 100644 +index a5d673dac5..0000000000 +--- a/src/pip/_vendor/toml/common.py ++++ /dev/null +@@ -1,6 +0,0 @@ +-# content after the \ +-escapes = ['0', 'b', 'f', 'n', 'r', 't', '"'] +-# What it should be replaced by +-escapedchars = ['\0', '\b', '\f', '\n', '\r', '\t', '\"'] +-# Used for substitution +-escape_to_escapedchars = dict(zip(_escapes, _escapedchars)) +diff --git a/src/pip/_vendor/toml/decoder.py b/src/pip/_vendor/toml/decoder.py +index e4887770c3..e071100de0 100644 +--- a/src/pip/_vendor/toml/decoder.py ++++ b/src/pip/_vendor/toml/decoder.py +@@ -440,7 +440,8 @@ def loads(s, _dict=dict, decoder=None): + groups[i][0] == "'"): + groupstr = groups[i] + j = i + 1 +- while not groupstr[0] == groupstr[-1]: ++ while ((not groupstr[0] == groupstr[-1]) or ++ len(groupstr) == 1): + j += 1 + if j > len(groups) + 2: + raise TomlDecodeError("Invalid group name '" + +@@ -811,8 +812,12 @@ def load_value(self, v, strictly_valid=True): + raise ValueError("Empty value is invalid") + if v == 'true': + return (True, "bool") ++ elif v.lower() == 'true': ++ raise ValueError("Only all lowercase booleans allowed") + elif v == 'false': + return (False, "bool") ++ elif v.lower() == 'false': ++ raise ValueError("Only all lowercase booleans allowed") + elif v[0] == '"' or v[0] == "'": + quotechar = v[0] + testv = v[1:].split(quotechar) +diff --git a/src/pip/_vendor/toml/encoder.py b/src/pip/_vendor/toml/encoder.py +index a8b03c7bea..7fb94da98a 100644 +--- a/src/pip/_vendor/toml/encoder.py ++++ b/src/pip/_vendor/toml/encoder.py +@@ -61,7 +61,7 @@ def dumps(o, encoder=None): + retval += addtoretval + outer_objs = [id(o)] + while sections: +- section_ids = [id(section) for section in sections] ++ section_ids = [id(section) for section in sections.values()] + for outer_obj in outer_objs: + if outer_obj in section_ids: + raise ValueError("Circular reference detected") +diff --git a/src/pip/_vendor/toml/tz.py b/src/pip/_vendor/toml/tz.py +index 93c3c8ad26..bf20593a26 100644 +--- a/src/pip/_vendor/toml/tz.py ++++ b/src/pip/_vendor/toml/tz.py +@@ -11,6 +11,9 @@ def __init__(self, toml_offset): + self._hours = int(self._raw_offset[1:3]) + self._minutes = int(self._raw_offset[4:6]) + ++ def __deepcopy__(self, memo): ++ return self.__class__(self._raw_offset) ++ + def tzname(self, dt): + return "UTC" + self._raw_offset + +diff --git a/src/pip/_vendor/urllib3/LICENSE.txt b/src/pip/_vendor/urllib3/LICENSE.txt +index c89cf27b85..429a1767e4 100644 +--- a/src/pip/_vendor/urllib3/LICENSE.txt ++++ b/src/pip/_vendor/urllib3/LICENSE.txt +@@ -1,6 +1,6 @@ + MIT License + +-Copyright (c) 2008-2019 Andrey Petrov and contributors (see CONTRIBUTORS.txt) ++Copyright (c) 2008-2020 Andrey Petrov and contributors (see CONTRIBUTORS.txt) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal +diff --git a/src/pip/_vendor/urllib3/__init__.py b/src/pip/_vendor/urllib3/__init__.py +index 667e9bce9e..fe86b59d78 100644 +--- a/src/pip/_vendor/urllib3/__init__.py ++++ b/src/pip/_vendor/urllib3/__init__.py +@@ -1,28 +1,27 @@ + """ +-urllib3 - Thread-safe connection pooling and re-using. ++Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more + """ + from __future__ import absolute_import +-import warnings + +-from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url ++# Set default logging handler to avoid "No handler found" warnings. ++import logging ++import warnings ++from logging import NullHandler + + from . import exceptions ++from ._version import __version__ ++from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url + from .filepost import encode_multipart_formdata + from .poolmanager import PoolManager, ProxyManager, proxy_from_url + from .response import HTTPResponse + from .util.request import make_headers +-from .util.url import get_host +-from .util.timeout import Timeout + from .util.retry import Retry +- +- +-# Set default logging handler to avoid "No handler found" warnings. +-import logging +-from logging import NullHandler ++from .util.timeout import Timeout ++from .util.url import get_host + + __author__ = "Andrey Petrov (andrey.petrov@shazow.net)" + __license__ = "MIT" +-__version__ = "1.25.9" ++__version__ = __version__ + + __all__ = ( + "HTTPConnectionPool", +diff --git a/src/pip/_vendor/urllib3/_collections.py b/src/pip/_vendor/urllib3/_collections.py +index 019d1511d5..da9857e986 100644 +--- a/src/pip/_vendor/urllib3/_collections.py ++++ b/src/pip/_vendor/urllib3/_collections.py +@@ -17,9 +17,10 @@ def __exit__(self, exc_type, exc_value, traceback): + + + from collections import OrderedDict +-from .exceptions import InvalidHeader +-from .packages.six import iterkeys, itervalues, PY3 + ++from .exceptions import InvalidHeader ++from .packages import six ++from .packages.six import iterkeys, itervalues + + __all__ = ["RecentlyUsedContainer", "HTTPHeaderDict"] + +@@ -174,7 +175,7 @@ def __eq__(self, other): + def __ne__(self, other): + return not self.__eq__(other) + +- if not PY3: # Python 2 ++ if six.PY2: # Python 2 + iterkeys = MutableMapping.iterkeys + itervalues = MutableMapping.itervalues + +@@ -190,7 +191,7 @@ def __iter__(self): + + def pop(self, key, default=__marker): + """D.pop(k[,d]) -> v, remove specified key and return the corresponding value. +- If key is not found, d is returned if given, otherwise KeyError is raised. ++ If key is not found, d is returned if given, otherwise KeyError is raised. + """ + # Using the MutableMapping function directly fails due to the private marker. + # Using ordinary dict.pop would expose the internal structures. +diff --git a/src/pip/_vendor/urllib3/_version.py b/src/pip/_vendor/urllib3/_version.py +new file mode 100644 +index 0000000000..2dba29e3fb +--- /dev/null ++++ b/src/pip/_vendor/urllib3/_version.py +@@ -0,0 +1,2 @@ ++# This file is protected via CODEOWNERS ++__version__ = "1.26.2" +diff --git a/src/pip/_vendor/urllib3/connection.py b/src/pip/_vendor/urllib3/connection.py +index 6da1cf4b6d..660d679c36 100644 +--- a/src/pip/_vendor/urllib3/connection.py ++++ b/src/pip/_vendor/urllib3/connection.py +@@ -1,14 +1,18 @@ + from __future__ import absolute_import +-import re ++ + import datetime + import logging + import os ++import re + import socket +-from socket import error as SocketError, timeout as SocketTimeout + import warnings ++from socket import error as SocketError ++from socket import timeout as SocketTimeout ++ + from .packages import six + from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection + from .packages.six.moves.http_client import HTTPException # noqa: F401 ++from .util.proxy import create_proxy_ssl_context + + try: # Compiled with SSL? + import ssl +@@ -30,27 +34,33 @@ class ConnectionError(Exception): + pass + + ++try: # Python 3: ++ # Not a no-op, we're adding this to the namespace so it can be imported. ++ BrokenPipeError = BrokenPipeError ++except NameError: # Python 2: ++ ++ class BrokenPipeError(Exception): ++ pass ++ ++ ++from ._collections import HTTPHeaderDict # noqa (historical, removed in v2) ++from ._version import __version__ + from .exceptions import ( +- NewConnectionError, + ConnectTimeoutError, ++ NewConnectionError, + SubjectAltNameWarning, + SystemTimeWarning, + ) +-from .packages.ssl_match_hostname import match_hostname, CertificateError +- ++from .packages.ssl_match_hostname import CertificateError, match_hostname ++from .util import SKIP_HEADER, SKIPPABLE_HEADERS, connection + from .util.ssl_ import ( +- resolve_cert_reqs, +- resolve_ssl_version, + assert_fingerprint, + create_urllib3_context, ++ resolve_cert_reqs, ++ resolve_ssl_version, + ssl_wrap_socket, + ) + +- +-from .util import connection +- +-from ._collections import HTTPHeaderDict +- + log = logging.getLogger(__name__) + + port_by_scheme = {"http": 80, "https": 443} +@@ -62,34 +72,30 @@ class ConnectionError(Exception): + _CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]") + + +-class DummyConnection(object): +- """Used to detect a failed ConnectionCls import.""" +- +- pass +- +- + class HTTPConnection(_HTTPConnection, object): + """ +- Based on httplib.HTTPConnection but provides an extra constructor ++ Based on :class:`http.client.HTTPConnection` but provides an extra constructor + backwards-compatibility layer between older and newer Pythons. + + Additional keyword parameters are used to configure attributes of the connection. + Accepted parameters include: + +- - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` +- - ``source_address``: Set the source address for the current connection. +- - ``socket_options``: Set specific options on the underlying socket. If not specified, then +- defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling +- Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. ++ - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` ++ - ``source_address``: Set the source address for the current connection. ++ - ``socket_options``: Set specific options on the underlying socket. If not specified, then ++ defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling ++ Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. + +- For example, if you wish to enable TCP Keep Alive in addition to the defaults, +- you might pass:: ++ For example, if you wish to enable TCP Keep Alive in addition to the defaults, ++ you might pass: + +- HTTPConnection.default_socket_options + [ +- (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), +- ] ++ .. code-block:: python + +- Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). ++ HTTPConnection.default_socket_options + [ ++ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), ++ ] ++ ++ Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). + """ + + default_port = port_by_scheme["http"] +@@ -112,6 +118,10 @@ def __init__(self, *args, **kw): + #: provided, we use the default options. + self.socket_options = kw.pop("socket_options", self.default_socket_options) + ++ # Proxy options provided by the user. ++ self.proxy = kw.pop("proxy", None) ++ self.proxy_config = kw.pop("proxy_config", None) ++ + _HTTPConnection.__init__(self, *args, **kw) + + @property +@@ -144,7 +154,7 @@ def host(self, value): + self._dns_host = value + + def _new_conn(self): +- """ Establish a socket connection and set nodelay settings on it. ++ """Establish a socket connection and set nodelay settings on it. + + :return: New socket connection. + """ +@@ -174,10 +184,13 @@ def _new_conn(self): + + return conn + ++ def _is_using_tunnel(self): ++ # Google App Engine's httplib does not define _tunnel_host ++ return getattr(self, "_tunnel_host", None) ++ + def _prepare_conn(self, conn): + self.sock = conn +- # Google App Engine's httplib does not define _tunnel_host +- if getattr(self, "_tunnel_host", None): ++ if self._is_using_tunnel(): + # TODO: Fix tunnel so it doesn't depend on self.sock state. + self._tunnel() + # Mark this connection as not reusable +@@ -188,7 +201,9 @@ def connect(self): + self._prepare_conn(conn) + + def putrequest(self, method, url, *args, **kwargs): +- """Send a request to the server""" ++ """""" ++ # Empty docstring because the indentation of CPython's implementation ++ # is broken but we don't want this method in our documentation. + match = _CONTAINS_CONTROL_CHAR_RE.search(method) + if match: + raise ValueError( +@@ -198,17 +213,40 @@ def putrequest(self, method, url, *args, **kwargs): + + return _HTTPConnection.putrequest(self, method, url, *args, **kwargs) + ++ def putheader(self, header, *values): ++ """""" ++ if SKIP_HEADER not in values: ++ _HTTPConnection.putheader(self, header, *values) ++ elif six.ensure_str(header.lower()) not in SKIPPABLE_HEADERS: ++ raise ValueError( ++ "urllib3.util.SKIP_HEADER only supports '%s'" ++ % ("', '".join(map(str.title, sorted(SKIPPABLE_HEADERS))),) ++ ) ++ ++ def request(self, method, url, body=None, headers=None): ++ if headers is None: ++ headers = {} ++ else: ++ # Avoid modifying the headers passed into .request() ++ headers = headers.copy() ++ if "user-agent" not in (six.ensure_str(k.lower()) for k in headers): ++ headers["User-Agent"] = _get_default_user_agent() ++ super(HTTPConnection, self).request(method, url, body=body, headers=headers) ++ + def request_chunked(self, method, url, body=None, headers=None): + """ + Alternative to the common request method, which sends the + body with chunked encoding and not as one block + """ +- headers = HTTPHeaderDict(headers if headers is not None else {}) +- skip_accept_encoding = "accept-encoding" in headers +- skip_host = "host" in headers ++ headers = headers or {} ++ header_keys = set([six.ensure_str(k.lower()) for k in headers]) ++ skip_accept_encoding = "accept-encoding" in header_keys ++ skip_host = "host" in header_keys + self.putrequest( + method, url, skip_accept_encoding=skip_accept_encoding, skip_host=skip_host + ) ++ if "user-agent" not in header_keys: ++ self.putheader("User-Agent", _get_default_user_agent()) + for header, value in headers.items(): + self.putheader(header, value) + if "transfer-encoding" not in headers: +@@ -225,16 +263,22 @@ def request_chunked(self, method, url, body=None, headers=None): + if not isinstance(chunk, bytes): + chunk = chunk.encode("utf8") + len_str = hex(len(chunk))[2:] +- self.send(len_str.encode("utf-8")) +- self.send(b"\r\n") +- self.send(chunk) +- self.send(b"\r\n") ++ to_send = bytearray(len_str.encode()) ++ to_send += b"\r\n" ++ to_send += chunk ++ to_send += b"\r\n" ++ self.send(to_send) + + # After the if clause, to always have a closed body + self.send(b"0\r\n\r\n") + + + class HTTPSConnection(HTTPConnection): ++ """ ++ Many of the parameters to this constructor are passed to the underlying SSL ++ socket by means of :py:func:`urllib3.util.ssl_wrap_socket`. ++ """ ++ + default_port = port_by_scheme["https"] + + cert_reqs = None +@@ -243,6 +287,7 @@ class HTTPSConnection(HTTPConnection): + ca_cert_data = None + ssl_version = None + assert_fingerprint = None ++ tls_in_tls_required = False + + def __init__( + self, +@@ -307,10 +352,15 @@ def connect(self): + # Add certificate verification + conn = self._new_conn() + hostname = self.host ++ tls_in_tls = False ++ ++ if self._is_using_tunnel(): ++ if self.tls_in_tls_required: ++ conn = self._connect_tls_proxy(hostname, conn) ++ tls_in_tls = True + +- # 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() +@@ -368,8 +418,26 @@ def connect(self): + ca_cert_data=self.ca_cert_data, + server_hostname=server_hostname, + ssl_context=context, ++ tls_in_tls=tls_in_tls, + ) + ++ # If we're using all defaults and the connection ++ # is TLSv1 or TLSv1.1 we throw a DeprecationWarning ++ # for the host. ++ if ( ++ default_ssl_context ++ and self.ssl_version is None ++ and hasattr(self.sock, "version") ++ and self.sock.version() in {"TLSv1", "TLSv1.1"} ++ ): ++ warnings.warn( ++ "Negotiating TLSv1/TLSv1.1 by default is deprecated " ++ "and will be disabled in urllib3 v2.0.0. Connecting to " ++ "'%s' with '%s' can be enabled by explicitly opting-in " ++ "with 'ssl_version'" % (self.host, self.sock.version()), ++ DeprecationWarning, ++ ) ++ + if self.assert_fingerprint: + assert_fingerprint( + self.sock.getpeercert(binary_form=True), self.assert_fingerprint +@@ -400,6 +468,40 @@ def connect(self): + or self.assert_fingerprint is not None + ) + ++ def _connect_tls_proxy(self, hostname, conn): ++ """ ++ Establish a TLS connection to the proxy using the provided SSL context. ++ """ ++ proxy_config = self.proxy_config ++ ssl_context = proxy_config.ssl_context ++ if ssl_context: ++ # If the user provided a proxy context, we assume CA and client ++ # certificates have already been set ++ return ssl_wrap_socket( ++ sock=conn, ++ server_hostname=hostname, ++ ssl_context=ssl_context, ++ ) ++ ++ ssl_context = create_proxy_ssl_context( ++ self.ssl_version, ++ self.cert_reqs, ++ self.ca_certs, ++ self.ca_cert_dir, ++ self.ca_cert_data, ++ ) ++ ++ # If no cert was provided, use only the default options for server ++ # certificate validation ++ return ssl_wrap_socket( ++ sock=conn, ++ ca_certs=self.ca_certs, ++ ca_cert_dir=self.ca_cert_dir, ++ ca_cert_data=self.ca_cert_data, ++ server_hostname=hostname, ++ ssl_context=ssl_context, ++ ) ++ + + def _match_hostname(cert, asserted_hostname): + try: +@@ -416,6 +518,16 @@ def _match_hostname(cert, asserted_hostname): + raise + + ++def _get_default_user_agent(): ++ return "python-urllib3/%s" % __version__ ++ ++ ++class DummyConnection(object): ++ """Used to detect a failed ConnectionCls import.""" ++ ++ pass ++ ++ + if not ssl: + HTTPSConnection = DummyConnection # noqa: F811 + +diff --git a/src/pip/_vendor/urllib3/connectionpool.py b/src/pip/_vendor/urllib3/connectionpool.py +index 5f044dbd90..4708c5bfc7 100644 +--- a/src/pip/_vendor/urllib3/connectionpool.py ++++ b/src/pip/_vendor/urllib3/connectionpool.py +@@ -1,57 +1,53 @@ + from __future__ import absolute_import ++ + import errno + import logging ++import socket + import sys + import warnings ++from socket import error as SocketError ++from socket import timeout as SocketTimeout + +-from socket import error as SocketError, timeout as SocketTimeout +-import socket +- +- ++from .connection import ( ++ BaseSSLError, ++ BrokenPipeError, ++ DummyConnection, ++ HTTPConnection, ++ HTTPException, ++ HTTPSConnection, ++ VerifiedHTTPSConnection, ++ port_by_scheme, ++) + from .exceptions import ( + ClosedPoolError, +- ProtocolError, + EmptyPoolError, + HeaderParsingError, + HostChangedError, ++ InsecureRequestWarning, + LocationValueError, + MaxRetryError, ++ NewConnectionError, ++ ProtocolError, + ProxyError, + ReadTimeoutError, + SSLError, + TimeoutError, +- InsecureRequestWarning, +- NewConnectionError, + ) +-from .packages.ssl_match_hostname import CertificateError + from .packages import six + from .packages.six.moves import queue +-from .connection import ( +- port_by_scheme, +- DummyConnection, +- HTTPConnection, +- HTTPSConnection, +- VerifiedHTTPSConnection, +- HTTPException, +- BaseSSLError, +-) ++from .packages.ssl_match_hostname import CertificateError + from .request import RequestMethods + from .response import HTTPResponse +- + from .util.connection import is_connection_dropped ++from .util.proxy import connection_requires_http_tunnel ++from .util.queue import LifoQueue + from .util.request import set_file_position + from .util.response import assert_header_parsing + from .util.retry import Retry + from .util.timeout import Timeout +-from .util.url import ( +- get_host, +- parse_url, +- Url, +- _normalize_host as normalize_host, +- _encode_target, +-) +-from .util.queue import LifoQueue +- ++from .util.url import Url, _encode_target ++from .util.url import _normalize_host as normalize_host ++from .util.url import get_host, parse_url + + xrange = six.moves.xrange + +@@ -111,16 +107,16 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into +- :class:`httplib.HTTPConnection`. ++ :class:`http.client.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed +- into :class:`httplib.HTTPConnection`. ++ into :class:`http.client.HTTPConnection`. + + :param strict: + Causes BadStatusLine to be raised if the status line can't be parsed + as a valid HTTP/1.0 or 1.1 status line, passed into +- :class:`httplib.HTTPConnection`. ++ :class:`http.client.HTTPConnection`. + + .. note:: + Only works in Python 2. This parameter is ignored in Python 3. +@@ -154,11 +150,11 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see +- :class:`urllib3.connectionpool.ProxyManager`" ++ :class:`urllib3.ProxyManager` + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, +- instead, see :class:`urllib3.connectionpool.ProxyManager`" ++ instead, see :class:`urllib3.ProxyManager` + + :param \\**conn_kw: + Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, +@@ -181,6 +177,7 @@ def __init__( + retries=None, + _proxy=None, + _proxy_headers=None, ++ _proxy_config=None, + **conn_kw + ): + ConnectionPool.__init__(self, host, port) +@@ -202,6 +199,7 @@ def __init__( + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} ++ self.proxy_config = _proxy_config + + # Fill the queue up so that doing get() on it will block properly + for _ in xrange(maxsize): +@@ -218,6 +216,9 @@ def __init__( + # list. + self.conn_kw.setdefault("socket_options", []) + ++ self.conn_kw["proxy"] = self.proxy ++ self.conn_kw["proxy_config"] = self.proxy_config ++ + def _new_conn(self): + """ + Return a fresh :class:`HTTPConnection`. +@@ -272,7 +273,7 @@ def _get_conn(self, timeout=None): + conn.close() + if getattr(conn, "auto_open", 1) == 0: + # This is a proxied connection that has been mutated by +- # httplib._tunnel() and cannot be reused (since it would ++ # http.client._tunnel() and cannot be reused (since it would + # attempt to bypass the proxy) + conn = None + +@@ -384,12 +385,30 @@ def _make_request( + self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) + raise + +- # conn.request() calls httplib.*.request, not the method in ++ # conn.request() calls http.client.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. +- if chunked: +- conn.request_chunked(method, url, **httplib_request_kw) +- else: +- conn.request(method, url, **httplib_request_kw) ++ try: ++ if chunked: ++ conn.request_chunked(method, url, **httplib_request_kw) ++ else: ++ conn.request(method, url, **httplib_request_kw) ++ ++ # We are swallowing BrokenPipeError (errno.EPIPE) since the server is ++ # legitimately able to close the connection after sending a valid response. ++ # With this behaviour, the received response is still readable. ++ except BrokenPipeError: ++ # Python 3 ++ pass ++ except IOError as e: ++ # Python 2 and macOS/Linux ++ # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE is needed on macOS ++ # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ ++ if e.errno not in { ++ errno.EPIPE, ++ errno.ESHUTDOWN, ++ errno.EPROTOTYPE, ++ }: ++ raise + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout +@@ -532,10 +551,12 @@ def urlopen( + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + ++ :param url: ++ The URL to perform the request on. ++ + :param body: +- Data to send in the request body (useful for creating +- POST requests, see HTTPConnectionPool.post_url for +- more convenience). ++ Data to send in the request body, either :class:`str`, :class:`bytes`, ++ an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, +@@ -565,7 +586,7 @@ def urlopen( + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is +- consistent else will raise HostChangedError. When False, you can ++ consistent else will raise HostChangedError. When ``False``, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: +@@ -602,6 +623,10 @@ def urlopen( + Additional parameters are passed to + :meth:`urllib3.response.HTTPResponse.from_httplib` + """ ++ ++ parsed_url = parse_url(url) ++ destination_scheme = parsed_url.scheme ++ + if headers is None: + headers = self.headers + +@@ -619,7 +644,7 @@ def urlopen( + if url.startswith("/"): + url = six.ensure_str(_encode_target(url)) + else: +- url = six.ensure_str(parse_url(url).url) ++ url = six.ensure_str(parsed_url.url) + + conn = None + +@@ -634,10 +659,14 @@ def urlopen( + # [1] + release_this_conn = release_conn + +- # Merge the proxy headers. Only do this in HTTP. We have to copy the +- # headers dict so we can safely change it without those changes being +- # reflected in anyone else's copy. +- if self.scheme == "http": ++ http_tunnel_required = connection_requires_http_tunnel( ++ self.proxy, self.proxy_config, destination_scheme ++ ) ++ ++ # Merge the proxy headers. Only done when not using HTTP CONNECT. We ++ # have to copy the headers dict so we can safely change it without those ++ # changes being reflected in anyone else's copy. ++ if not http_tunnel_required: + headers = headers.copy() + headers.update(self.proxy_headers) + +@@ -663,7 +692,7 @@ def urlopen( + is_new_proxy_conn = self.proxy is not None and not getattr( + conn, "sock", None + ) +- if is_new_proxy_conn: ++ if is_new_proxy_conn and http_tunnel_required: + self._prepare_proxy(conn) + + # Make the request on the httplib connection object. +@@ -698,9 +727,11 @@ def urlopen( + # Everything went great! + clean_exit = True + +- except queue.Empty: +- # Timed out by queue. +- raise EmptyPoolError(self, "No pool connections are available.") ++ except EmptyPoolError: ++ # Didn't get a connection from the pool, no need to clean up ++ clean_exit = True ++ release_this_conn = False ++ raise + + except ( + TimeoutError, +@@ -835,11 +866,7 @@ class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + +- When Python is compiled with the :mod:`ssl` module, then +- :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, +- instead of :class:`.HTTPSConnection`. +- +- :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, ++ :class:`.HTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + +@@ -923,15 +950,22 @@ def _prepare_conn(self, conn): + + def _prepare_proxy(self, conn): + """ +- Establish tunnel connection early, because otherwise httplib +- would improperly set Host: header to proxy's IP:port. ++ Establishes a tunnel connection through HTTP CONNECT. ++ ++ Tunnel connection is established early because otherwise httplib would ++ improperly set Host: header to proxy's IP:port. + """ ++ + conn.set_tunnel(self._proxy_host, self.port, self.proxy_headers) ++ ++ if self.proxy.scheme == "https": ++ conn.tls_in_tls_required = True ++ + conn.connect() + + def _new_conn(self): + """ +- Return a fresh :class:`httplib.HTTPSConnection`. ++ Return a fresh :class:`http.client.HTTPSConnection`. + """ + self.num_connections += 1 + log.debug( +diff --git a/src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +index d9b6733318..42526be7f5 100644 +--- a/src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py ++++ b/src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +@@ -32,30 +32,26 @@ + from __future__ import absolute_import + + import platform +-from ctypes.util import find_library + from ctypes import ( +- c_void_p, +- c_int32, ++ CDLL, ++ CFUNCTYPE, ++ POINTER, ++ c_bool, ++ c_byte, + c_char_p, ++ c_int32, ++ c_long, + c_size_t, +- c_byte, + c_uint32, + c_ulong, +- c_long, +- c_bool, ++ c_void_p, + ) +-from ctypes import CDLL, POINTER, CFUNCTYPE +- +- +-security_path = find_library("Security") +-if not security_path: +- raise ImportError("The library Security could not be found") +- ++from ctypes.util import find_library + +-core_foundation_path = find_library("CoreFoundation") +-if not core_foundation_path: +- raise ImportError("The library CoreFoundation could not be found") ++from pip._vendor.urllib3.packages.six import raise_from + ++if platform.system() != "Darwin": ++ raise ImportError("Only macOS is supported") + + version = platform.mac_ver()[0] + version_info = tuple(map(int, version.split("."))) +@@ -65,8 +61,31 @@ + % (version_info[0], version_info[1]) + ) + +-Security = CDLL(security_path, use_errno=True) +-CoreFoundation = CDLL(core_foundation_path, use_errno=True) ++ ++def load_cdll(name, macos10_16_path): ++ """Loads a CDLL by name, falling back to known path on 10.16+""" ++ try: ++ # Big Sur is technically 11 but we use 10.16 due to the Big Sur ++ # beta being labeled as 10.16. ++ if version_info >= (10, 16): ++ path = macos10_16_path ++ else: ++ path = find_library(name) ++ if not path: ++ raise OSError # Caught and reraised as 'ImportError' ++ return CDLL(path, use_errno=True) ++ except OSError: ++ raise_from(ImportError("The library %s failed to load" % name), None) ++ ++ ++Security = load_cdll( ++ "Security", "/System/Library/Frameworks/Security.framework/Security" ++) ++CoreFoundation = load_cdll( ++ "CoreFoundation", ++ "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", ++) ++ + + Boolean = c_bool + CFIndex = c_long +@@ -276,6 +295,13 @@ + Security.SSLSetProtocolVersionMax.argtypes = [SSLContextRef, SSLProtocol] + Security.SSLSetProtocolVersionMax.restype = OSStatus + ++ try: ++ Security.SSLSetALPNProtocols.argtypes = [SSLContextRef, CFArrayRef] ++ Security.SSLSetALPNProtocols.restype = OSStatus ++ except AttributeError: ++ # Supported only in 10.12+ ++ pass ++ + Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] + Security.SecCopyErrorMessageString.restype = CFStringRef + +diff --git a/src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +index e60168cac1..ed8120190c 100644 +--- a/src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py ++++ b/src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +@@ -10,13 +10,13 @@ + import base64 + import ctypes + import itertools +-import re + import os ++import re + import ssl ++import struct + import tempfile + +-from .bindings import Security, CoreFoundation, CFConst +- ++from .bindings import CFConst, CoreFoundation, Security + + # This regular expression is used to grab PEM data out of a PEM bundle. + _PEM_CERTS_RE = re.compile( +@@ -56,6 +56,51 @@ def _cf_dictionary_from_tuples(tuples): + ) + + ++def _cfstr(py_bstr): ++ """ ++ Given a Python binary data, create a CFString. ++ The string must be CFReleased by the caller. ++ """ ++ c_str = ctypes.c_char_p(py_bstr) ++ cf_str = CoreFoundation.CFStringCreateWithCString( ++ CoreFoundation.kCFAllocatorDefault, ++ c_str, ++ CFConst.kCFStringEncodingUTF8, ++ ) ++ return cf_str ++ ++ ++def _create_cfstring_array(lst): ++ """ ++ Given a list of Python binary data, create an associated CFMutableArray. ++ The array must be CFReleased by the caller. ++ ++ Raises an ssl.SSLError on failure. ++ """ ++ cf_arr = None ++ try: ++ cf_arr = CoreFoundation.CFArrayCreateMutable( ++ CoreFoundation.kCFAllocatorDefault, ++ 0, ++ ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), ++ ) ++ if not cf_arr: ++ raise MemoryError("Unable to allocate memory!") ++ for item in lst: ++ cf_str = _cfstr(item) ++ if not cf_str: ++ raise MemoryError("Unable to allocate memory!") ++ try: ++ CoreFoundation.CFArrayAppendValue(cf_arr, cf_str) ++ finally: ++ CoreFoundation.CFRelease(cf_str) ++ except BaseException as e: ++ if cf_arr: ++ CoreFoundation.CFRelease(cf_arr) ++ raise ssl.SSLError("Unable to allocate array: %s" % (e,)) ++ return cf_arr ++ ++ + def _cf_string_to_unicode(value): + """ + Creates a Unicode string from a CFString object. Used entirely for error +@@ -326,3 +371,26 @@ def _load_client_cert_chain(keychain, *paths): + finally: + for obj in itertools.chain(identities, certificates): + CoreFoundation.CFRelease(obj) ++ ++ ++TLS_PROTOCOL_VERSIONS = { ++ "SSLv2": (0, 2), ++ "SSLv3": (3, 0), ++ "TLSv1": (3, 1), ++ "TLSv1.1": (3, 2), ++ "TLSv1.2": (3, 3), ++} ++ ++ ++def _build_tls_unknown_ca_alert(version): ++ """ ++ Builds a TLS alert record for an unknown CA. ++ """ ++ ver_maj, ver_min = TLS_PROTOCOL_VERSIONS[version] ++ severity_fatal = 0x02 ++ description_unknown_ca = 0x30 ++ msg = struct.pack(">BB", severity_fatal, description_unknown_ca) ++ msg_len = len(msg) ++ record_type_alert = 0x15 ++ record = struct.pack(">BBBH", record_type_alert, ver_maj, ver_min, msg_len) + msg ++ return record +diff --git a/src/pip/_vendor/urllib3/contrib/appengine.py b/src/pip/_vendor/urllib3/contrib/appengine.py +index d09d2be645..b9d2a6907c 100644 +--- a/src/pip/_vendor/urllib3/contrib/appengine.py ++++ b/src/pip/_vendor/urllib3/contrib/appengine.py +@@ -39,24 +39,24 @@ + """ + + from __future__ import absolute_import ++ + import io + import logging + import warnings +-from ..packages.six.moves.urllib.parse import urljoin + + from ..exceptions import ( + HTTPError, + HTTPWarning, + MaxRetryError, + ProtocolError, +- TimeoutError, + SSLError, ++ TimeoutError, + ) +- ++from ..packages.six.moves.urllib.parse import urljoin + from ..request import RequestMethods + from ..response import HTTPResponse +-from ..util.timeout import Timeout + from ..util.retry import Retry ++from ..util.timeout import Timeout + from . import _appengine_environ + + try: +@@ -90,7 +90,7 @@ class AppEngineManager(RequestMethods): + * If you attempt to use this on App Engine Flexible, as full socket + support is available. + * If a request size is more than 10 megabytes. +- * If a response size is more than 32 megabtyes. ++ * If a response size is more than 32 megabytes. + * If you use an unsupported request method such as OPTIONS. + + Beyond those cases, it will raise normal urllib3 errors. +diff --git a/src/pip/_vendor/urllib3/contrib/ntlmpool.py b/src/pip/_vendor/urllib3/contrib/ntlmpool.py +index 1fd242a6e0..b2df45dcf6 100644 +--- a/src/pip/_vendor/urllib3/contrib/ntlmpool.py ++++ b/src/pip/_vendor/urllib3/contrib/ntlmpool.py +@@ -6,12 +6,12 @@ + from __future__ import absolute_import + + from logging import getLogger ++ + from ntlm import ntlm + + from .. import HTTPSConnectionPool + from ..packages.six.moves.http_client import HTTPSConnection + +- + log = getLogger(__name__) + + +diff --git a/src/pip/_vendor/urllib3/contrib/pyopenssl.py b/src/pip/_vendor/urllib3/contrib/pyopenssl.py +index d8fe0629c4..bc5c114fa7 100644 +--- a/src/pip/_vendor/urllib3/contrib/pyopenssl.py ++++ b/src/pip/_vendor/urllib3/contrib/pyopenssl.py +@@ -1,27 +1,31 @@ + """ +-SSL with SNI_-support for Python 2. Follow these instructions if you would +-like to verify SSL certificates in Python 2. Note, the default libraries do ++TLS with SNI_-support for Python 2. Follow these instructions if you would ++like to verify TLS certificates in Python 2. Note, the default libraries do + *not* do certificate checking; you need to do additional work to validate + certificates yourself. + + This needs the following packages installed: + +-* pyOpenSSL (tested with 16.0.0) +-* cryptography (minimum 1.3.4, from pyopenssl) +-* idna (minimum 2.0, from cryptography) ++* `pyOpenSSL`_ (tested with 16.0.0) ++* `cryptography`_ (minimum 1.3.4, from pyopenssl) ++* `idna`_ (minimum 2.0, from cryptography) + + However, pyopenssl depends on cryptography, which depends on idna, so while we + use all three directly here we end up having relatively few packages required. + + You can install them with the following command: + +- pip install pyopenssl cryptography idna ++.. code-block:: bash ++ ++ $ python -m pip install pyopenssl cryptography idna + + To activate certificate checking, call + :func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code + before you begin making HTTP requests. This can be done in a ``sitecustomize`` + module, or at any other time before your application begins using ``urllib3``, +-like this:: ++like this: ++ ++.. code-block:: python + + try: + import urllib3.contrib.pyopenssl +@@ -35,11 +39,11 @@ + Activating this module also has the positive side effect of disabling SSL/TLS + compression in Python 2 (see `CRIME attack`_). + +-If you want to configure the default list of supported cipher suites, you can +-set the ``urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST`` variable. +- + .. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication + .. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit) ++.. _pyopenssl: https://www.pyopenssl.org ++.. _cryptography: https://cryptography.io ++.. _idna: https://github.com/kjd/idna + """ + from __future__ import absolute_import + +@@ -56,8 +60,9 @@ class UnsupportedExtension(Exception): + pass + + +-from socket import timeout, error as SocketError + from io import BytesIO ++from socket import error as SocketError ++from socket import timeout + + try: # Platform-specific: Python 2 + from socket import _fileobject +@@ -67,11 +72,10 @@ class UnsupportedExtension(Exception): + + import logging + import ssl +-from ..packages import six + import sys + + from .. import util +- ++from ..packages import six + + __all__ = ["inject_into_urllib3", "extract_from_urllib3"] + +@@ -465,6 +469,10 @@ def load_cert_chain(self, certfile, keyfile=None, password=None): + self._ctx.set_passwd_cb(lambda *_: password) + self._ctx.use_privatekey_file(keyfile or certfile) + ++ def set_alpn_protocols(self, protocols): ++ protocols = [six.ensure_binary(p) for p in protocols] ++ return self._ctx.set_alpn_protos(protocols) ++ + def wrap_socket( + self, + sock, +diff --git a/src/pip/_vendor/urllib3/contrib/securetransport.py b/src/pip/_vendor/urllib3/contrib/securetransport.py +index a6b7e94ade..8f058f5070 100644 +--- a/src/pip/_vendor/urllib3/contrib/securetransport.py ++++ b/src/pip/_vendor/urllib3/contrib/securetransport.py +@@ -29,6 +29,8 @@ + that reason, this code should be considered to be covered both by urllib3's + license and by oscrypto's: + ++.. code-block:: ++ + Copyright (c) 2015-2016 Will Bond + + Permission is hereby granted, free of charge, to any person obtaining a +@@ -58,16 +60,21 @@ + import shutil + import socket + import ssl ++import struct + import threading + import weakref + ++from pip._vendor import six ++ + from .. import util +-from ._securetransport.bindings import Security, SecurityConst, CoreFoundation ++from ._securetransport.bindings import CoreFoundation, Security, SecurityConst + from ._securetransport.low_level import ( + _assert_no_error, ++ _build_tls_unknown_ca_alert, + _cert_array_from_pem, +- _temporary_keychain, ++ _create_cfstring_array, + _load_client_cert_chain, ++ _temporary_keychain, + ) + + try: # Platform-specific: Python 2 +@@ -374,16 +381,55 @@ def _set_ciphers(self): + ) + _assert_no_error(result) + ++ def _set_alpn_protocols(self, protocols): ++ """ ++ Sets up the ALPN protocols on the context. ++ """ ++ if not protocols: ++ return ++ protocols_arr = _create_cfstring_array(protocols) ++ try: ++ result = Security.SSLSetALPNProtocols(self.context, protocols_arr) ++ _assert_no_error(result) ++ finally: ++ CoreFoundation.CFRelease(protocols_arr) ++ + def _custom_validate(self, verify, trust_bundle): + """ + Called when we have set custom validation. We do this in two cases: + first, when cert validation is entirely disabled; and second, when + using a custom trust DB. ++ Raises an SSLError if the connection is not trusted. + """ + # If we disabled cert validation, just say: cool. + if not verify: + return + ++ successes = ( ++ SecurityConst.kSecTrustResultUnspecified, ++ SecurityConst.kSecTrustResultProceed, ++ ) ++ try: ++ trust_result = self._evaluate_trust(trust_bundle) ++ if trust_result in successes: ++ return ++ reason = "error code: %d" % (trust_result,) ++ except Exception as e: ++ # Do not trust on error ++ reason = "exception: %r" % (e,) ++ ++ # SecureTransport does not send an alert nor shuts down the connection. ++ rec = _build_tls_unknown_ca_alert(self.version()) ++ self.socket.sendall(rec) ++ # close the connection immediately ++ # l_onoff = 1, activate linger ++ # l_linger = 0, linger for 0 seoncds ++ opts = struct.pack("ii", 1, 0) ++ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, opts) ++ self.close() ++ raise ssl.SSLError("certificate verify failed, %s" % reason) ++ ++ def _evaluate_trust(self, trust_bundle): + # We want data in memory, so load it up. + if os.path.isfile(trust_bundle): + with open(trust_bundle, "rb") as f: +@@ -421,15 +467,7 @@ def _custom_validate(self, verify, trust_bundle): + if cert_array is not None: + CoreFoundation.CFRelease(cert_array) + +- # Ok, now we can look at what the result was. +- successes = ( +- SecurityConst.kSecTrustResultUnspecified, +- SecurityConst.kSecTrustResultProceed, +- ) +- if trust_result.value not in successes: +- raise ssl.SSLError( +- "certificate verify failed, error code: %d" % trust_result.value +- ) ++ return trust_result.value + + def handshake( + self, +@@ -441,6 +479,7 @@ def handshake( + client_cert, + client_key, + client_key_passphrase, ++ alpn_protocols, + ): + """ + Actually performs the TLS handshake. This is run automatically by +@@ -481,6 +520,9 @@ def handshake( + # Setup the ciphers. + self._set_ciphers() + ++ # Setup the ALPN protocols. ++ self._set_alpn_protocols(alpn_protocols) ++ + # Set the minimum and maximum TLS versions. + result = Security.SSLSetProtocolVersionMin(self.context, min_version) + _assert_no_error(result) +@@ -754,6 +796,7 @@ def __init__(self, protocol): + self._client_cert = None + self._client_key = None + self._client_key_passphrase = None ++ self._alpn_protocols = None + + @property + def check_hostname(self): +@@ -831,6 +874,18 @@ def load_cert_chain(self, certfile, keyfile=None, password=None): + self._client_key = keyfile + self._client_cert_passphrase = password + ++ def set_alpn_protocols(self, protocols): ++ """ ++ Sets the ALPN protocols that will later be set on the context. ++ ++ Raises a NotImplementedError if ALPN is not supported. ++ """ ++ if not hasattr(Security, "SSLSetALPNProtocols"): ++ raise NotImplementedError( ++ "SecureTransport supports ALPN only in macOS 10.12+" ++ ) ++ self._alpn_protocols = [six.ensure_binary(p) for p in protocols] ++ + def wrap_socket( + self, + sock, +@@ -860,5 +915,6 @@ def wrap_socket( + self._client_cert, + self._client_key, + self._client_key_passphrase, ++ self._alpn_protocols, + ) + return wrapped_socket +diff --git a/src/pip/_vendor/urllib3/contrib/socks.py b/src/pip/_vendor/urllib3/contrib/socks.py +index 9e97f7aa98..93df8325d5 100644 +--- a/src/pip/_vendor/urllib3/contrib/socks.py ++++ b/src/pip/_vendor/urllib3/contrib/socks.py +@@ -14,22 +14,26 @@ + - SOCKS5 with local DNS (``proxy_url='socks5://...``) + - Usernames and passwords for the SOCKS proxy + +- .. note:: +- It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in +- your ``proxy_url`` to ensure that DNS resolution is done from the remote +- server instead of client-side when connecting to a domain name. ++.. note:: ++ It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in ++ your ``proxy_url`` to ensure that DNS resolution is done from the remote ++ server instead of client-side when connecting to a domain name. + + SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5 + supports IPv4, IPv6, and domain names. + + When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url`` +-will be sent as the ``userid`` section of the SOCKS request:: ++will be sent as the ``userid`` section of the SOCKS request: ++ ++.. code-block:: python + + proxy_url="socks4a://@proxy-host" + + When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion + of the ``proxy_url`` will be sent as the username/password to authenticate +-with the proxy:: ++with the proxy: ++ ++.. code-block:: python + + proxy_url="socks5h://:@proxy-host" + +@@ -40,6 +44,7 @@ + import socks + except ImportError: + import warnings ++ + from ..exceptions import DependencyWarning + + warnings.warn( +@@ -52,7 +57,8 @@ + ) + raise + +-from socket import error as SocketError, timeout as SocketTimeout ++from socket import error as SocketError ++from socket import timeout as SocketTimeout + + from ..connection import HTTPConnection, HTTPSConnection + from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool +diff --git a/src/pip/_vendor/urllib3/exceptions.py b/src/pip/_vendor/urllib3/exceptions.py +index 5cc4d8a4f1..d69958d5df 100644 +--- a/src/pip/_vendor/urllib3/exceptions.py ++++ b/src/pip/_vendor/urllib3/exceptions.py +@@ -1,21 +1,24 @@ + from __future__ import absolute_import ++ + from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead + + # Base Exceptions + + + class HTTPError(Exception): +- "Base exception used by this module." ++ """Base exception used by this module.""" ++ + pass + + + class HTTPWarning(Warning): +- "Base warning used by this module." ++ """Base warning used by this module.""" ++ + pass + + + class PoolError(HTTPError): +- "Base exception for errors caused within a pool." ++ """Base exception for errors caused within a pool.""" + + def __init__(self, pool, message): + self.pool = pool +@@ -27,7 +30,7 @@ def __reduce__(self): + + + class RequestError(PoolError): +- "Base exception for PoolErrors that have associated URLs." ++ """Base exception for PoolErrors that have associated URLs.""" + + def __init__(self, pool, url, message): + self.url = url +@@ -39,12 +42,13 @@ def __reduce__(self): + + + class SSLError(HTTPError): +- "Raised when SSL certificate fails in an HTTPS connection." ++ """Raised when SSL certificate fails in an HTTPS connection.""" ++ + pass + + + class ProxyError(HTTPError): +- "Raised when the connection to a proxy fails." ++ """Raised when the connection to a proxy fails.""" + + def __init__(self, message, error, *args): + super(ProxyError, self).__init__(message, error, *args) +@@ -52,12 +56,14 @@ def __init__(self, message, error, *args): + + + class DecodeError(HTTPError): +- "Raised when automatic decoding based on Content-Type fails." ++ """Raised when automatic decoding based on Content-Type fails.""" ++ + pass + + + class ProtocolError(HTTPError): +- "Raised when something unexpected happens mid-request/response." ++ """Raised when something unexpected happens mid-request/response.""" ++ + pass + + +@@ -87,7 +93,7 @@ def __init__(self, pool, url, reason=None): + + + class HostChangedError(RequestError): +- "Raised when an existing pool gets a request for a foreign host." ++ """Raised when an existing pool gets a request for a foreign host.""" + + def __init__(self, pool, url, retries=3): + message = "Tried to open a foreign host with url: %s" % url +@@ -96,13 +102,13 @@ def __init__(self, pool, url, retries=3): + + + class TimeoutStateError(HTTPError): +- """ Raised when passing an invalid state to a timeout """ ++ """Raised when passing an invalid state to a timeout""" + + pass + + + class TimeoutError(HTTPError): +- """ Raised when a socket timeout error occurs. ++ """Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + ` and :exc:`ConnectTimeoutErrors `. +@@ -112,39 +118,45 @@ class TimeoutError(HTTPError): + + + class ReadTimeoutError(TimeoutError, RequestError): +- "Raised when a socket timeout occurs while receiving data from a server" ++ """Raised when a socket timeout occurs while receiving data from a server""" ++ + pass + + + # This timeout error does not have a URL attached and needs to inherit from the + # base HTTPError + class ConnectTimeoutError(TimeoutError): +- "Raised when a socket timeout occurs while connecting to a server" ++ """Raised when a socket timeout occurs while connecting to a server""" ++ + pass + + + class NewConnectionError(ConnectTimeoutError, PoolError): +- "Raised when we fail to establish a new connection. Usually ECONNREFUSED." ++ """Raised when we fail to establish a new connection. Usually ECONNREFUSED.""" ++ + pass + + + class EmptyPoolError(PoolError): +- "Raised when a pool runs out of connections and no more are allowed." ++ """Raised when a pool runs out of connections and no more are allowed.""" ++ + pass + + + class ClosedPoolError(PoolError): +- "Raised when a request enters a pool after the pool has been closed." ++ """Raised when a request enters a pool after the pool has been closed.""" ++ + pass + + + class LocationValueError(ValueError, HTTPError): +- "Raised when there is something wrong with a given URL input." ++ """Raised when there is something wrong with a given URL input.""" ++ + pass + + + class LocationParseError(LocationValueError): +- "Raised when get_host or similar fails to parse the URL input." ++ """Raised when get_host or similar fails to parse the URL input.""" + + def __init__(self, location): + message = "Failed to parse: %s" % location +@@ -153,39 +165,56 @@ def __init__(self, location): + self.location = location + + ++class URLSchemeUnknown(LocationValueError): ++ """Raised when a URL input has an unsupported scheme.""" ++ ++ def __init__(self, scheme): ++ message = "Not supported URL scheme %s" % scheme ++ super(URLSchemeUnknown, self).__init__(message) ++ ++ self.scheme = scheme ++ ++ + class ResponseError(HTTPError): +- "Used as a container for an error reason supplied in a MaxRetryError." ++ """Used as a container for an error reason supplied in a MaxRetryError.""" ++ + GENERIC_ERROR = "too many error responses" + SPECIFIC_ERROR = "too many {status_code} error responses" + + + class SecurityWarning(HTTPWarning): +- "Warned when performing security reducing actions" ++ """Warned when performing security reducing actions""" ++ + pass + + + class SubjectAltNameWarning(SecurityWarning): +- "Warned when connecting to a host with a certificate missing a SAN." ++ """Warned when connecting to a host with a certificate missing a SAN.""" ++ + pass + + + class InsecureRequestWarning(SecurityWarning): +- "Warned when making an unverified HTTPS request." ++ """Warned when making an unverified HTTPS request.""" ++ + pass + + + class SystemTimeWarning(SecurityWarning): +- "Warned when system time is suspected to be wrong" ++ """Warned when system time is suspected to be wrong""" ++ + pass + + + class InsecurePlatformWarning(SecurityWarning): +- "Warned when certain SSL configuration is not available on a platform." ++ """Warned when certain TLS/SSL configuration is not available on a platform.""" ++ + pass + + + class SNIMissingWarning(HTTPWarning): +- "Warned when making a HTTPS request without SNI available." ++ """Warned when making a HTTPS request without SNI available.""" ++ + pass + + +@@ -198,29 +227,16 @@ class DependencyWarning(HTTPWarning): + pass + + +-class InvalidProxyConfigurationWarning(HTTPWarning): +- """ +- Warned when using an HTTPS proxy and an HTTPS URL. Currently +- urllib3 doesn't support HTTPS proxies and the proxy will be +- contacted via HTTP instead. This warning can be fixed by +- changing your HTTPS proxy URL into an HTTP proxy URL. +- +- If you encounter this warning read this: +- https://github.com/urllib3/urllib3/issues/1850 +- """ +- +- pass +- +- + class ResponseNotChunked(ProtocolError, ValueError): +- "Response needs to be chunked in order to read it as chunks." ++ """Response needs to be chunked in order to read it as chunks.""" ++ + pass + + + class BodyNotHttplibCompatible(HTTPError): + """ +- Body should be httplib.HTTPResponse like (have an fp attribute which +- returns raw chunks) for read_chunked(). ++ Body should be :class:`http.client.HTTPResponse` like ++ (have an fp attribute which returns raw chunks) for read_chunked(). + """ + + pass +@@ -230,9 +246,8 @@ class IncompleteRead(HTTPError, httplib_IncompleteRead): + """ + Response length doesn't match expected Content-Length + +- Subclass of http_client.IncompleteRead to allow int value +- for `partial` to avoid creating large objects on streamed +- reads. ++ Subclass of :class:`http.client.IncompleteRead` to allow int value ++ for ``partial`` to avoid creating large objects on streamed reads. + """ + + def __init__(self, partial, expected): +@@ -245,13 +260,32 @@ def __repr__(self): + ) + + ++class InvalidChunkLength(HTTPError, httplib_IncompleteRead): ++ """Invalid chunk length in a chunked response.""" ++ ++ def __init__(self, response, length): ++ super(InvalidChunkLength, self).__init__( ++ response.tell(), response.length_remaining ++ ) ++ self.response = response ++ self.length = length ++ ++ def __repr__(self): ++ return "InvalidChunkLength(got length %r, %i bytes read)" % ( ++ self.length, ++ self.partial, ++ ) ++ ++ + class InvalidHeader(HTTPError): +- "The header provided was somehow invalid." ++ """The header provided was somehow invalid.""" ++ + pass + + +-class ProxySchemeUnknown(AssertionError, ValueError): +- "ProxyManager does not support the supplied scheme" ++class ProxySchemeUnknown(AssertionError, URLSchemeUnknown): ++ """ProxyManager does not support the supplied scheme""" ++ + # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. + + def __init__(self, scheme): +@@ -259,8 +293,14 @@ def __init__(self, scheme): + super(ProxySchemeUnknown, self).__init__(message) + + ++class ProxySchemeUnsupported(ValueError): ++ """Fetching HTTPS resources through HTTPS proxies is unsupported""" ++ ++ pass ++ ++ + class HeaderParsingError(HTTPError): +- "Raised by assert_header_parsing, but we convert it to a log.warning statement." ++ """Raised by assert_header_parsing, but we convert it to a log.warning statement.""" + + def __init__(self, defects, unparsed_data): + message = "%s, unparsed data: %r" % (defects or "Unknown", unparsed_data) +@@ -268,5 +308,6 @@ def __init__(self, defects, unparsed_data): + + + class UnrewindableBodyError(HTTPError): +- "urllib3 encountered an error when trying to rewind a body" ++ """urllib3 encountered an error when trying to rewind a body""" ++ + pass +diff --git a/src/pip/_vendor/urllib3/fields.py b/src/pip/_vendor/urllib3/fields.py +index 8715b2202b..9d630f491d 100644 +--- a/src/pip/_vendor/urllib3/fields.py ++++ b/src/pip/_vendor/urllib3/fields.py +@@ -1,4 +1,5 @@ + from __future__ import absolute_import ++ + import email.utils + import mimetypes + import re +@@ -26,7 +27,8 @@ def format_header_param_rfc2231(name, value): + strategy defined in RFC 2231. + + Particularly useful for header parameters which might contain +- non-ASCII values, like file names. This follows RFC 2388 Section 4.4. ++ non-ASCII values, like file names. This follows ++ `RFC 2388 Section 4.4 `_. + + :param name: + The name of the parameter, a string expected to be ASCII only. +@@ -65,7 +67,6 @@ def format_header_param_rfc2231(name, value): + u"\u0022": u"%22", + # Replace "\" with "\\". + u"\u005C": u"\u005C\u005C", +- u"\u005C": u"\u005C\u005C", + } + + # All control characters from 0x00 to 0x1F *except* 0x1B. +diff --git a/src/pip/_vendor/urllib3/filepost.py b/src/pip/_vendor/urllib3/filepost.py +index b7b00992c6..36c9252c64 100644 +--- a/src/pip/_vendor/urllib3/filepost.py ++++ b/src/pip/_vendor/urllib3/filepost.py +@@ -1,13 +1,13 @@ + from __future__ import absolute_import ++ + import binascii + import codecs + import os +- + from io import BytesIO + ++from .fields import RequestField + from .packages import six + from .packages.six import b +-from .fields import RequestField + + writer = codecs.lookup("utf-8")[3] + +diff --git a/src/pip/_vendor/urllib3/packages/backports/makefile.py b/src/pip/_vendor/urllib3/packages/backports/makefile.py +index a3156a69c0..b8fb2154b6 100644 +--- a/src/pip/_vendor/urllib3/packages/backports/makefile.py ++++ b/src/pip/_vendor/urllib3/packages/backports/makefile.py +@@ -7,7 +7,6 @@ + wants to create a "fake" socket object. + """ + import io +- + from socket import SocketIO + + +diff --git a/src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py b/src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py +index 75b6bb1cf0..6b12fd90aa 100644 +--- a/src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py ++++ b/src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py +@@ -10,10 +10,13 @@ + except ImportError: + try: + # Backport of the function from a pypi module +- from backports.ssl_match_hostname import CertificateError, match_hostname ++ from backports.ssl_match_hostname import ( # type: ignore ++ CertificateError, ++ match_hostname, ++ ) + except ImportError: + # Our vendored copy +- from ._implementation import CertificateError, match_hostname ++ from ._implementation import CertificateError, match_hostname # type: ignore + + # Not needed, but documenting what we provide. + __all__ = ("CertificateError", "match_hostname") +diff --git a/src/pip/_vendor/urllib3/poolmanager.py b/src/pip/_vendor/urllib3/poolmanager.py +index e2bd3bd8db..3a31a285bf 100644 +--- a/src/pip/_vendor/urllib3/poolmanager.py ++++ b/src/pip/_vendor/urllib3/poolmanager.py +@@ -1,24 +1,24 @@ + from __future__ import absolute_import ++ + import collections + import functools + import logging +-import warnings + + from ._collections import RecentlyUsedContainer +-from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool +-from .connectionpool import port_by_scheme ++from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme + from .exceptions import ( + LocationValueError, + MaxRetryError, + ProxySchemeUnknown, +- InvalidProxyConfigurationWarning, ++ ProxySchemeUnsupported, ++ URLSchemeUnknown, + ) + from .packages import six + from .packages.six.moves.urllib.parse import urljoin + from .request import RequestMethods +-from .util.url import parse_url ++from .util.proxy import connection_requires_http_tunnel + from .util.retry import Retry +- ++from .util.url import parse_url + + __all__ = ["PoolManager", "ProxyManager", "proxy_from_url"] + +@@ -59,6 +59,7 @@ + "key_headers", # dict + "key__proxy", # parsed proxy url + "key__proxy_headers", # dict ++ "key__proxy_config", # class + "key_socket_options", # list of (level (int), optname (int), value (int or str)) tuples + "key__socks_options", # dict + "key_assert_hostname", # bool or string +@@ -70,6 +71,9 @@ + #: All custom key schemes should include the fields in this key at a minimum. + PoolKey = collections.namedtuple("PoolKey", _key_fields) + ++_proxy_config_fields = ("ssl_context", "use_forwarding_for_https") ++ProxyConfig = collections.namedtuple("ProxyConfig", _proxy_config_fields) ++ + + def _default_key_normalizer(key_class, request_context): + """ +@@ -161,6 +165,7 @@ class PoolManager(RequestMethods): + """ + + proxy = None ++ proxy_config = None + + def __init__(self, num_pools=10, headers=None, **connection_pool_kw): + RequestMethods.__init__(self, headers) +@@ -182,7 +187,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): + + def _new_pool(self, scheme, host, port, request_context=None): + """ +- Create a new :class:`ConnectionPool` based on host, port, scheme, and ++ Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and + any additional pool keyword arguments. + + If ``request_context`` is provided, it is provided as keyword arguments +@@ -218,7 +223,7 @@ def clear(self): + + def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None): + """ +- Get a :class:`ConnectionPool` based on the host, port, and scheme. ++ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is +@@ -241,20 +246,22 @@ def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None) + + def connection_from_context(self, request_context): + """ +- Get a :class:`ConnectionPool` based on the request context. ++ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context. + + ``request_context`` must at least contain the ``scheme`` key and its + value must be a key in ``key_fn_by_scheme`` instance variable. + """ + scheme = request_context["scheme"].lower() +- pool_key_constructor = self.key_fn_by_scheme[scheme] ++ pool_key_constructor = self.key_fn_by_scheme.get(scheme) ++ if not pool_key_constructor: ++ raise URLSchemeUnknown(scheme) + pool_key = pool_key_constructor(request_context) + + return self.connection_from_pool_key(pool_key, request_context=request_context) + + def connection_from_pool_key(self, pool_key, request_context=None): + """ +- Get a :class:`ConnectionPool` based on the provided pool key. ++ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key. + + ``pool_key`` should be a namedtuple that only contains immutable + objects. At a minimum it must have the ``scheme``, ``host``, and +@@ -312,9 +319,39 @@ def _merge_pool_kwargs(self, override): + base_pool_kwargs[key] = value + return base_pool_kwargs + ++ def _proxy_requires_url_absolute_form(self, parsed_url): ++ """ ++ Indicates if the proxy requires the complete destination URL in the ++ request. Normally this is only needed when not using an HTTP CONNECT ++ tunnel. ++ """ ++ if self.proxy is None: ++ return False ++ ++ return not connection_requires_http_tunnel( ++ self.proxy, self.proxy_config, parsed_url.scheme ++ ) ++ ++ def _validate_proxy_scheme_url_selection(self, url_scheme): ++ """ ++ Validates that were not attempting to do TLS in TLS connections on ++ Python2 or with unsupported SSL implementations. ++ """ ++ if self.proxy is None or url_scheme != "https": ++ return ++ ++ if self.proxy.scheme != "https": ++ return ++ ++ if six.PY2 and not self.proxy_config.use_forwarding_for_https: ++ raise ProxySchemeUnsupported( ++ "Contacting HTTPS destinations through HTTPS proxies " ++ "'via CONNECT tunnels' is not supported in Python 2" ++ ) ++ + def urlopen(self, method, url, redirect=True, **kw): + """ +- Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` ++ Same as :meth:`urllib3.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + +@@ -322,6 +359,8 @@ def urlopen(self, method, url, redirect=True, **kw): + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) ++ self._validate_proxy_scheme_url_selection(u.scheme) ++ + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw["assert_same_host"] = False +@@ -330,7 +369,7 @@ def urlopen(self, method, url, redirect=True, **kw): + if "headers" not in kw: + kw["headers"] = self.headers.copy() + +- if self.proxy is not None and u.scheme == "http": ++ if self._proxy_requires_url_absolute_form(u): + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) +@@ -392,6 +431,19 @@ class ProxyManager(PoolManager): + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + ++ :param proxy_ssl_context: ++ The proxy SSL context is used to establish the TLS connection to the ++ proxy when using HTTPS proxies. ++ ++ :param use_forwarding_for_https: ++ (Defaults to False) If set to True will forward requests to the HTTPS ++ proxy to be made on behalf of the client instead of creating a TLS ++ tunnel via the CONNECT method. **Enabling this flag means that request ++ and response headers and content will be visible from the HTTPS proxy** ++ whereas tunneling keeps request and response headers and content ++ private. IP address, target hostname, SNI, and port are always visible ++ to an HTTPS proxy even when this flag is disabled. ++ + Example: + >>> proxy = urllib3.ProxyManager('http://localhost:3128/') + >>> r1 = proxy.request('GET', 'http://google.com/') +@@ -411,6 +463,8 @@ def __init__( + num_pools=10, + headers=None, + proxy_headers=None, ++ proxy_ssl_context=None, ++ use_forwarding_for_https=False, + **connection_pool_kw + ): + +@@ -421,18 +475,22 @@ def __init__( + proxy_url.port, + ) + proxy = parse_url(proxy_url) +- if not proxy.port: +- port = port_by_scheme.get(proxy.scheme, 80) +- proxy = proxy._replace(port=port) + + if proxy.scheme not in ("http", "https"): + raise ProxySchemeUnknown(proxy.scheme) + ++ if not proxy.port: ++ port = port_by_scheme.get(proxy.scheme, 80) ++ proxy = proxy._replace(port=port) ++ + self.proxy = proxy + self.proxy_headers = proxy_headers or {} ++ self.proxy_ssl_context = proxy_ssl_context ++ self.proxy_config = ProxyConfig(proxy_ssl_context, use_forwarding_for_https) + + connection_pool_kw["_proxy"] = self.proxy + connection_pool_kw["_proxy_headers"] = self.proxy_headers ++ connection_pool_kw["_proxy_config"] = self.proxy_config + + super(ProxyManager, self).__init__(num_pools, headers, **connection_pool_kw) + +@@ -461,27 +519,13 @@ def _set_proxy_headers(self, url, headers=None): + headers_.update(headers) + return headers_ + +- def _validate_proxy_scheme_url_selection(self, url_scheme): +- if url_scheme == "https" and self.proxy.scheme == "https": +- warnings.warn( +- "Your proxy configuration specified an HTTPS scheme for the proxy. " +- "Are you sure you want to use HTTPS to contact the proxy? " +- "This most likely indicates an error in your configuration. " +- "Read this issue for more info: " +- "https://github.com/urllib3/urllib3/issues/1850", +- InvalidProxyConfigurationWarning, +- stacklevel=3, +- ) +- + def urlopen(self, method, url, redirect=True, **kw): + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) +- self._validate_proxy_scheme_url_selection(u.scheme) +- +- if u.scheme == "http": +- # For proxied HTTPS requests, httplib sets the necessary headers +- # on the CONNECT to the proxy. For HTTP, we'll definitely +- # need to set 'Host' at the very least. ++ if not connection_requires_http_tunnel(self.proxy, self.proxy_config, u.scheme): ++ # For connections using HTTP CONNECT, httplib sets the necessary ++ # headers on the CONNECT to the proxy. If we're not using CONNECT, ++ # we'll definitely need to set 'Host' at the very least. + headers = kw.get("headers", self.headers) + kw["headers"] = self._set_proxy_headers(url, headers) + +diff --git a/src/pip/_vendor/urllib3/request.py b/src/pip/_vendor/urllib3/request.py +index 55f160bbf1..398386a5b9 100644 +--- a/src/pip/_vendor/urllib3/request.py ++++ b/src/pip/_vendor/urllib3/request.py +@@ -3,15 +3,14 @@ + from .filepost import encode_multipart_formdata + from .packages.six.moves.urllib.parse import urlencode + +- + __all__ = ["RequestMethods"] + + + class RequestMethods(object): + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such +- as :class:`~urllib3.connectionpool.HTTPConnectionPool` and +- :class:`~urllib3.poolmanager.PoolManager`. ++ as :class:`urllib3.HTTPConnectionPool` and ++ :class:`urllib3.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. +@@ -111,9 +110,9 @@ def request_encode_body( + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then +- :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode ++ :func:`urllib3.encode_multipart_formdata` is used to encode + the payload with the appropriate content type. Otherwise +- :meth:`urllib.urlencode` is used with the ++ :func:`urllib.parse.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably +diff --git a/src/pip/_vendor/urllib3/response.py b/src/pip/_vendor/urllib3/response.py +index 7dc9b93cae..38693f4fc6 100644 +--- a/src/pip/_vendor/urllib3/response.py ++++ b/src/pip/_vendor/urllib3/response.py +@@ -1,10 +1,11 @@ + from __future__ import absolute_import +-from contextlib import contextmanager +-import zlib ++ + import io + import logging +-from socket import timeout as SocketTimeout ++import zlib ++from contextlib import contextmanager + from socket import error as SocketError ++from socket import timeout as SocketTimeout + + try: + import brotli +@@ -12,19 +13,20 @@ + brotli = None + + from ._collections import HTTPHeaderDict ++from .connection import BaseSSLError, HTTPException + from .exceptions import ( + BodyNotHttplibCompatible, +- ProtocolError, + DecodeError, +- ReadTimeoutError, +- ResponseNotChunked, ++ HTTPError, + IncompleteRead, ++ InvalidChunkLength, + InvalidHeader, +- HTTPError, ++ ProtocolError, ++ ReadTimeoutError, ++ ResponseNotChunked, ++ SSLError, + ) +-from .packages.six import string_types as basestring, PY3 +-from .packages.six.moves import http_client as httplib +-from .connection import HTTPException, BaseSSLError ++from .packages import six + from .util.response import is_fp_closed, is_response_to_head + + log = logging.getLogger(__name__) +@@ -107,11 +109,10 @@ class BrotliDecoder(object): + # 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) ++ self.decompress = self._obj.decompress ++ else: ++ self.decompress = self._obj.process + + def flush(self): + if hasattr(self._obj, "flush"): +@@ -157,13 +158,13 @@ class HTTPResponse(io.IOBase): + """ + HTTP Response container. + +- Backwards-compatible to httplib's HTTPResponse but the response ``body`` is ++ Backwards-compatible with :class:`http.client.HTTPResponse` but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. This + class is also compatible with the Python standard library's :mod:`io` + module, and can hence be treated as a readable object in the context of that + framework. + +- Extra parameters for behaviour not present in httplib.HTTPResponse: ++ Extra parameters for behaviour not present in :class:`http.client.HTTPResponse`: + + :param preload_content: + If True, the response's body will be preloaded during construction. +@@ -173,7 +174,7 @@ class is also compatible with the Python standard library's :mod:`io` + 'content-encoding' header. + + :param original_response: +- When this HTTPResponse wrapper is generated from an httplib.HTTPResponse ++ When this HTTPResponse wrapper is generated from an :class:`http.client.HTTPResponse` + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + +@@ -233,7 +234,7 @@ def __init__( + self.msg = msg + self._request_url = request_url + +- if body and isinstance(body, (basestring, bytes)): ++ if body and isinstance(body, (six.string_types, bytes)): + self._body = body + + self._pool = pool +@@ -291,7 +292,7 @@ def drain_conn(self): + + @property + def data(self): +- # For backwords-compat with earlier urllib3 0.4 and earlier. ++ # For backwards-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body + +@@ -308,8 +309,8 @@ def isclosed(self): + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from +- the amount of content returned by :meth:``HTTPResponse.read`` if bytes +- are encoded on the wire (e.g, compressed). ++ the amount of content returned by :meth:``urllib3.response.HTTPResponse.read`` ++ if bytes are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + +@@ -443,10 +444,9 @@ def _error_catcher(self): + + except BaseSSLError as e: + # FIXME: Is there a better way to differentiate between SSLErrors? +- if "read operation timed out" not in str(e): # Defensive: +- # This shouldn't happen but just in case we're missing an edge +- # case, let's avoid swallowing SSL errors. +- raise ++ if "read operation timed out" not in str(e): ++ # SSL errors related to framing/MAC get wrapped and reraised here ++ raise SSLError(e) + + raise ReadTimeoutError(self._pool, None, "Read timed out.") + +@@ -480,7 +480,7 @@ def _error_catcher(self): + + def read(self, amt=None, decode_content=None, cache_content=False): + """ +- Similar to :meth:`httplib.HTTPResponse.read`, but with two additional ++ Similar to :meth:`http.client.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: +@@ -581,7 +581,7 @@ def stream(self, amt=2 ** 16, decode_content=None): + @classmethod + def from_httplib(ResponseCls, r, **response_kw): + """ +- Given an :class:`httplib.HTTPResponse` instance ``r``, return a ++ Given an :class:`http.client.HTTPResponse` instance ``r``, return a + corresponding :class:`urllib3.response.HTTPResponse` object. + + Remaining parameters are passed to the HTTPResponse constructor, along +@@ -590,11 +590,11 @@ def from_httplib(ResponseCls, r, **response_kw): + headers = r.msg + + if not isinstance(headers, HTTPHeaderDict): +- if PY3: +- headers = HTTPHeaderDict(headers.items()) +- else: ++ if six.PY2: + # Python 2.7 + headers = HTTPHeaderDict.from_httplib(headers) ++ else: ++ headers = HTTPHeaderDict(headers.items()) + + # HTTPResponse objects in Python 3 don't have a .strict attribute + strict = getattr(r, "strict", 0) +@@ -610,7 +610,7 @@ def from_httplib(ResponseCls, r, **response_kw): + ) + return resp + +- # Backwards-compatibility methods for httplib.HTTPResponse ++ # Backwards-compatibility methods for http.client.HTTPResponse + def getheaders(self): + return self.headers + +@@ -680,8 +680,8 @@ def readinto(self, b): + def supports_chunked_reads(self): + """ + Checks if the underlying file-like object looks like a +- httplib.HTTPResponse object. We do this by testing for the fp +- attribute. If it is present we assume it returns raw chunks as ++ :class:`http.client.HTTPResponse` object. We do this by testing for ++ the fp attribute. If it is present we assume it returns raw chunks as + processed by read_chunked(). + """ + return hasattr(self._fp, "fp") +@@ -698,7 +698,7 @@ def _update_chunk_length(self): + except ValueError: + # Invalid chunked protocol response, abort. + self.close() +- raise httplib.IncompleteRead(line) ++ raise InvalidChunkLength(self, line) + + def _handle_chunk(self, amt): + returned_chunk = None +@@ -745,7 +745,7 @@ def read_chunked(self, amt=None, decode_content=None): + ) + if not self.supports_chunked_reads(): + raise BodyNotHttplibCompatible( +- "Body should be httplib.HTTPResponse like. " ++ "Body should be http.client.HTTPResponse like. " + "It should have have an fp attribute which returns raw chunks." + ) + +diff --git a/src/pip/_vendor/urllib3/util/__init__.py b/src/pip/_vendor/urllib3/util/__init__.py +index a96c73a9d8..4547fc522b 100644 +--- a/src/pip/_vendor/urllib3/util/__init__.py ++++ b/src/pip/_vendor/urllib3/util/__init__.py +@@ -2,23 +2,23 @@ + + # For backwards compatibility, provide imports that used to be here. + from .connection import is_connection_dropped +-from .request import make_headers ++from .request import SKIP_HEADER, SKIPPABLE_HEADERS, make_headers + from .response import is_fp_closed ++from .retry import Retry + from .ssl_ import ( +- SSLContext, ++ ALPN_PROTOCOLS, + HAS_SNI, + IS_PYOPENSSL, + IS_SECURETRANSPORT, ++ PROTOCOL_TLS, ++ SSLContext, + assert_fingerprint, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +- PROTOCOL_TLS, + ) +-from .timeout import current_time, Timeout +- +-from .retry import Retry +-from .url import get_host, parse_url, split_first, Url ++from .timeout import Timeout, current_time ++from .url import Url, get_host, parse_url, split_first + from .wait import wait_for_read, wait_for_write + + __all__ = ( +@@ -27,6 +27,7 @@ + "IS_SECURETRANSPORT", + "SSLContext", + "PROTOCOL_TLS", ++ "ALPN_PROTOCOLS", + "Retry", + "Timeout", + "Url", +@@ -43,4 +44,6 @@ + "ssl_wrap_socket", + "wait_for_read", + "wait_for_write", ++ "SKIP_HEADER", ++ "SKIPPABLE_HEADERS", + ) +diff --git a/src/pip/_vendor/urllib3/util/connection.py b/src/pip/_vendor/urllib3/util/connection.py +index 86f0a3b00e..f1e5d37f88 100644 +--- a/src/pip/_vendor/urllib3/util/connection.py ++++ b/src/pip/_vendor/urllib3/util/connection.py +@@ -1,7 +1,12 @@ + from __future__ import absolute_import ++ + import socket +-from .wait import NoWayToWaitForSocketError, wait_for_read ++ ++from pip._vendor.urllib3.exceptions import LocationParseError ++ + from ..contrib import _appengine_environ ++from ..packages import six ++from .wait import NoWayToWaitForSocketError, wait_for_read + + + def is_connection_dropped(conn): # Platform-specific +@@ -9,7 +14,7 @@ def is_connection_dropped(conn): # Platform-specific + Returns True if the connection is dropped and should be closed. + + :param conn: +- :class:`httplib.HTTPConnection` object. ++ :class:`http.client.HTTPConnection` object. + + Note: For platforms like AppEngine, this will always return ``False`` to + let the platform handle connection recycling transparently for us. +@@ -42,7 +47,7 @@ def create_connection( + port)``) and return the socket object. Passing the optional + *timeout* parameter will set the timeout on the socket instance + before attempting to connect. If no *timeout* is supplied, the +- global default timeout setting returned by :func:`getdefaulttimeout` ++ global default timeout setting returned by :func:`socket.getdefaulttimeout` + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of '' or port 0 tells the OS to use the default. +@@ -58,6 +63,13 @@ def create_connection( + # The original create_connection function always returns all records. + family = allowed_gai_family() + ++ try: ++ host.encode("idna") ++ except UnicodeError: ++ return six.raise_from( ++ LocationParseError(u"'%s', label empty or too long" % host), None ++ ) ++ + for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None +diff --git a/src/pip/_vendor/urllib3/util/proxy.py b/src/pip/_vendor/urllib3/util/proxy.py +new file mode 100644 +index 0000000000..34f884d5b3 +--- /dev/null ++++ b/src/pip/_vendor/urllib3/util/proxy.py +@@ -0,0 +1,56 @@ ++from .ssl_ import create_urllib3_context, resolve_cert_reqs, resolve_ssl_version ++ ++ ++def connection_requires_http_tunnel( ++ proxy_url=None, proxy_config=None, destination_scheme=None ++): ++ """ ++ Returns True if the connection requires an HTTP CONNECT through the proxy. ++ ++ :param URL proxy_url: ++ URL of the proxy. ++ :param ProxyConfig proxy_config: ++ Proxy configuration from poolmanager.py ++ :param str destination_scheme: ++ The scheme of the destination. (i.e https, http, etc) ++ """ ++ # If we're not using a proxy, no way to use a tunnel. ++ if proxy_url is None: ++ return False ++ ++ # HTTP destinations never require tunneling, we always forward. ++ if destination_scheme == "http": ++ return False ++ ++ # Support for forwarding with HTTPS proxies and HTTPS destinations. ++ if ( ++ proxy_url.scheme == "https" ++ and proxy_config ++ and proxy_config.use_forwarding_for_https ++ ): ++ return False ++ ++ # Otherwise always use a tunnel. ++ return True ++ ++ ++def create_proxy_ssl_context( ++ ssl_version, cert_reqs, ca_certs=None, ca_cert_dir=None, ca_cert_data=None ++): ++ """ ++ Generates a default proxy ssl context if one hasn't been provided by the ++ user. ++ """ ++ ssl_context = create_urllib3_context( ++ ssl_version=resolve_ssl_version(ssl_version), ++ cert_reqs=resolve_cert_reqs(cert_reqs), ++ ) ++ if ( ++ not ca_certs ++ and not ca_cert_dir ++ and not ca_cert_data ++ and hasattr(ssl_context, "load_default_certs") ++ ): ++ ssl_context.load_default_certs() ++ ++ return ssl_context +diff --git a/src/pip/_vendor/urllib3/util/queue.py b/src/pip/_vendor/urllib3/util/queue.py +index d3d379a199..41784104ee 100644 +--- a/src/pip/_vendor/urllib3/util/queue.py ++++ b/src/pip/_vendor/urllib3/util/queue.py +@@ -1,4 +1,5 @@ + import collections ++ + from ..packages import six + from ..packages.six.moves import queue + +diff --git a/src/pip/_vendor/urllib3/util/request.py b/src/pip/_vendor/urllib3/util/request.py +index 3b7bb54daf..25103383ec 100644 +--- a/src/pip/_vendor/urllib3/util/request.py ++++ b/src/pip/_vendor/urllib3/util/request.py +@@ -1,8 +1,16 @@ + from __future__ import absolute_import ++ + from base64 import b64encode + +-from ..packages.six import b, integer_types + from ..exceptions import UnrewindableBodyError ++from ..packages.six import b, integer_types ++ ++# Pass as a value within ``headers`` to skip ++# emitting some HTTP headers that are added automatically. ++# The only headers that are supported are ``Accept-Encoding``, ++# ``Host``, and ``User-Agent``. ++SKIP_HEADER = "@@@SKIP_HEADER@@@" ++SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"]) + + ACCEPT_ENCODING = "gzip,deflate" + try: +diff --git a/src/pip/_vendor/urllib3/util/response.py b/src/pip/_vendor/urllib3/util/response.py +index 715868dd10..5ea609cced 100644 +--- a/src/pip/_vendor/urllib3/util/response.py ++++ b/src/pip/_vendor/urllib3/util/response.py +@@ -1,7 +1,9 @@ + from __future__ import absolute_import +-from ..packages.six.moves import http_client as httplib ++ ++from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect + + from ..exceptions import HeaderParsingError ++from ..packages.six.moves import http_client as httplib + + + def is_fp_closed(obj): +@@ -42,8 +44,7 @@ def assert_header_parsing(headers): + + Only works on Python 3. + +- :param headers: Headers to verify. +- :type headers: `httplib.HTTPMessage`. ++ :param http.client.HTTPMessage headers: Headers to verify. + + :raises urllib3.exceptions.HeaderParsingError: + If parsing errors are found. +@@ -66,6 +67,25 @@ def assert_header_parsing(headers): + + if isinstance(payload, (bytes, str)): + unparsed_data = payload ++ if defects: ++ # httplib is assuming a response body is available ++ # when parsing headers even when httplib only sends ++ # header data to parse_headers() This results in ++ # defects on multipart responses in particular. ++ # See: https://github.com/urllib3/urllib3/issues/800 ++ ++ # So we ignore the following defects: ++ # - StartBoundaryNotFoundDefect: ++ # The claimed start boundary was never found. ++ # - MultipartInvariantViolationDefect: ++ # A message claimed to be a multipart but no subparts were found. ++ defects = [ ++ defect ++ for defect in defects ++ if not isinstance( ++ defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect) ++ ) ++ ] + + if defects or unparsed_data: + raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) +@@ -76,8 +96,9 @@ def is_response_to_head(response): + Checks whether the request of a response has been a HEAD-request. + Handles the quirks of AppEngine. + +- :param conn: +- :type conn: :class:`httplib.HTTPResponse` ++ :param http.client.HTTPResponse response: ++ Response to check if the originating request ++ used 'HEAD' as a method. + """ + # FIXME: Can we do this somehow without accessing private httplib _method? + method = response._method +diff --git a/src/pip/_vendor/urllib3/util/retry.py b/src/pip/_vendor/urllib3/util/retry.py +index ee30c91b14..ee51f922f8 100644 +--- a/src/pip/_vendor/urllib3/util/retry.py ++++ b/src/pip/_vendor/urllib3/util/retry.py +@@ -1,23 +1,24 @@ + from __future__ import absolute_import +-import time ++ ++import email + import logging ++import re ++import time ++import warnings + from collections import namedtuple + from itertools import takewhile +-import email +-import re + + from ..exceptions import ( + ConnectTimeoutError, ++ InvalidHeader, + MaxRetryError, + ProtocolError, ++ ProxyError, + ReadTimeoutError, + ResponseError, +- InvalidHeader, +- ProxyError, + ) + from ..packages import six + +- + log = logging.getLogger(__name__) + + +@@ -27,8 +28,51 @@ + ) + + ++# TODO: In v2 we can remove this sentinel and metaclass with deprecated options. ++_Default = object() ++ ++ ++class _RetryMeta(type): ++ @property ++ def DEFAULT_METHOD_WHITELIST(cls): ++ warnings.warn( ++ "Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and " ++ "will be removed in v2.0. Use 'Retry.DEFAULT_METHODS_ALLOWED' instead", ++ DeprecationWarning, ++ ) ++ return cls.DEFAULT_ALLOWED_METHODS ++ ++ @DEFAULT_METHOD_WHITELIST.setter ++ def DEFAULT_METHOD_WHITELIST(cls, value): ++ warnings.warn( ++ "Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and " ++ "will be removed in v2.0. Use 'Retry.DEFAULT_ALLOWED_METHODS' instead", ++ DeprecationWarning, ++ ) ++ cls.DEFAULT_ALLOWED_METHODS = value ++ ++ @property ++ def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls): ++ warnings.warn( ++ "Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and " ++ "will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead", ++ DeprecationWarning, ++ ) ++ return cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT ++ ++ @DEFAULT_REDIRECT_HEADERS_BLACKLIST.setter ++ def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls, value): ++ warnings.warn( ++ "Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and " ++ "will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead", ++ DeprecationWarning, ++ ) ++ cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT = value ++ ++ ++@six.add_metaclass(_RetryMeta) + class Retry(object): +- """ Retry configuration. ++ """Retry configuration. + + Each retry attempt will create a new Retry object with updated values, so + they can be safely reused. +@@ -54,8 +98,7 @@ class Retry(object): + Total number of retries to allow. Takes precedence over other counts. + + Set to ``None`` to remove this constraint and fall back on other +- counts. It's a good idea to set this to some sensibly-high value to +- account for unexpected edge cases and avoid infinite retry loops. ++ counts. + + Set to ``0`` to fail on the first retry. + +@@ -96,18 +139,35 @@ class Retry(object): + + Set to ``0`` to fail on the first retry of this type. + +- :param iterable method_whitelist: ++ :param int other: ++ How many times to retry on other errors. ++ ++ Other errors are errors that are not connect, read, redirect or status errors. ++ These errors might be raised after the request was sent to the server, so the ++ request might have side-effects. ++ ++ Set to ``0`` to fail on the first retry of this type. ++ ++ If ``total`` is not set, it's a good idea to set this to 0 to account ++ for unexpected edge cases and avoid infinite retry loops. ++ ++ :param iterable allowed_methods: + Set of uppercased HTTP method verbs that we should retry on. + + By default, we only retry on methods which are considered to be + idempotent (multiple requests with the same parameters end with the +- same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`. ++ same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`. + + Set to a ``False`` value to retry on any verb. + ++ .. warning:: ++ ++ Previously this parameter was named ``method_whitelist``, that ++ usage is deprecated in v1.26.0 and will be removed in v2.0. ++ + :param iterable status_forcelist: + A set of integer HTTP status codes that we should force a retry on. +- A retry is initiated if the request method is in ``method_whitelist`` ++ A retry is initiated if the request method is in ``allowed_methods`` + and the response status code is in ``status_forcelist``. + + By default, this is disabled with ``None``. +@@ -148,13 +208,16 @@ class Retry(object): + request. + """ + +- DEFAULT_METHOD_WHITELIST = frozenset( ++ #: Default methods to be used for ``allowed_methods`` ++ DEFAULT_ALLOWED_METHODS = frozenset( + ["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"] + ) + ++ #: Default status codes to be used for ``status_forcelist`` + RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) + +- DEFAULT_REDIRECT_HEADERS_BLACKLIST = frozenset(["Authorization"]) ++ #: Default headers to be used for ``remove_headers_on_redirect`` ++ DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Authorization"]) + + #: Maximum backoff time. + BACKOFF_MAX = 120 +@@ -166,20 +229,42 @@ def __init__( + read=None, + redirect=None, + status=None, +- method_whitelist=DEFAULT_METHOD_WHITELIST, ++ other=None, ++ allowed_methods=_Default, + status_forcelist=None, + backoff_factor=0, + raise_on_redirect=True, + raise_on_status=True, + history=None, + respect_retry_after_header=True, +- remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST, ++ remove_headers_on_redirect=_Default, ++ # TODO: Deprecated, remove in v2.0 ++ method_whitelist=_Default, + ): + ++ if method_whitelist is not _Default: ++ if allowed_methods is not _Default: ++ raise ValueError( ++ "Using both 'allowed_methods' and " ++ "'method_whitelist' together is not allowed. " ++ "Instead only use 'allowed_methods'" ++ ) ++ warnings.warn( ++ "Using 'method_whitelist' with Retry is deprecated and " ++ "will be removed in v2.0. Use 'allowed_methods' instead", ++ DeprecationWarning, ++ ) ++ allowed_methods = method_whitelist ++ if allowed_methods is _Default: ++ allowed_methods = self.DEFAULT_ALLOWED_METHODS ++ if remove_headers_on_redirect is _Default: ++ remove_headers_on_redirect = self.DEFAULT_REMOVE_HEADERS_ON_REDIRECT ++ + self.total = total + self.connect = connect + self.read = read + self.status = status ++ self.other = other + + if redirect is False or total is False: + redirect = 0 +@@ -187,7 +272,7 @@ def __init__( + + self.redirect = redirect + self.status_forcelist = status_forcelist or set() +- self.method_whitelist = method_whitelist ++ self.allowed_methods = allowed_methods + self.backoff_factor = backoff_factor + self.raise_on_redirect = raise_on_redirect + self.raise_on_status = raise_on_status +@@ -204,7 +289,7 @@ def new(self, **kw): + read=self.read, + redirect=self.redirect, + status=self.status, +- method_whitelist=self.method_whitelist, ++ other=self.other, + status_forcelist=self.status_forcelist, + backoff_factor=self.backoff_factor, + raise_on_redirect=self.raise_on_redirect, +@@ -213,6 +298,23 @@ def new(self, **kw): + remove_headers_on_redirect=self.remove_headers_on_redirect, + respect_retry_after_header=self.respect_retry_after_header, + ) ++ ++ # TODO: If already given in **kw we use what's given to us ++ # If not given we need to figure out what to pass. We decide ++ # based on whether our class has the 'method_whitelist' property ++ # and if so we pass the deprecated 'method_whitelist' otherwise ++ # we use 'allowed_methods'. Remove in v2.0 ++ if "method_whitelist" not in kw and "allowed_methods" not in kw: ++ if "method_whitelist" in self.__dict__: ++ warnings.warn( ++ "Using 'method_whitelist' with Retry is deprecated and " ++ "will be removed in v2.0. Use 'allowed_methods' instead", ++ DeprecationWarning, ++ ) ++ params["method_whitelist"] = self.allowed_methods ++ else: ++ params["allowed_methods"] = self.allowed_methods ++ + params.update(kw) + return type(self)(**params) + +@@ -231,7 +333,7 @@ def from_int(cls, retries, redirect=True, default=None): + return new_retries + + def get_backoff_time(self): +- """ Formula for computing the current backoff ++ """Formula for computing the current backoff + + :rtype: float + """ +@@ -252,10 +354,17 @@ def parse_retry_after(self, retry_after): + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = int(retry_after) + else: +- retry_date_tuple = email.utils.parsedate(retry_after) ++ retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + raise InvalidHeader("Invalid Retry-After header: %s" % retry_after) +- retry_date = time.mktime(retry_date_tuple) ++ if retry_date_tuple[9] is None: # Python 2 ++ # Assume UTC if no timezone was specified ++ # On Python2.7, parsedate_tz returns None for a timezone offset ++ # instead of 0 if no timezone is given, where mktime_tz treats ++ # a None timezone offset as local time. ++ retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:] ++ ++ retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: +@@ -288,7 +397,7 @@ def _sleep_backoff(self): + time.sleep(backoff) + + def sleep(self, response=None): +- """ Sleep between retry attempts. ++ """Sleep between retry attempts. + + This method will respect a server's ``Retry-After`` response header + and sleep the duration of the time requested. If that is not present, it +@@ -304,7 +413,7 @@ def sleep(self, response=None): + self._sleep_backoff() + + def _is_connection_error(self, err): +- """ Errors when we're fairly sure that the server did not receive the ++ """Errors when we're fairly sure that the server did not receive the + request, so it should be safe to retry. + """ + if isinstance(err, ProxyError): +@@ -312,22 +421,33 @@ def _is_connection_error(self, err): + return isinstance(err, ConnectTimeoutError) + + def _is_read_error(self, err): +- """ Errors that occur after the request has been started, so we should ++ """Errors that occur after the request has been started, so we should + assume that the server began processing it. + """ + return isinstance(err, (ReadTimeoutError, ProtocolError)) + + def _is_method_retryable(self, method): +- """ Checks if a given HTTP method should be retried upon, depending if +- it is included on the method whitelist. ++ """Checks if a given HTTP method should be retried upon, depending if ++ it is included in the allowed_methods + """ +- if self.method_whitelist and method.upper() not in self.method_whitelist: +- return False ++ # TODO: For now favor if the Retry implementation sets its own method_whitelist ++ # property outside of our constructor to avoid breaking custom implementations. ++ if "method_whitelist" in self.__dict__: ++ warnings.warn( ++ "Using 'method_whitelist' with Retry is deprecated and " ++ "will be removed in v2.0. Use 'allowed_methods' instead", ++ DeprecationWarning, ++ ) ++ allowed_methods = self.method_whitelist ++ else: ++ allowed_methods = self.allowed_methods + ++ if allowed_methods and method.upper() not in allowed_methods: ++ return False + return True + + def is_retry(self, method, status_code, has_retry_after=False): +- """ Is this method/status code retryable? (Based on whitelists and control ++ """Is this method/status code retryable? (Based on allowlists and control + variables such as the number of total retries to allow, whether to + respect the Retry-After header, whether this header is present, and + whether the returned status code is on the list of status codes to +@@ -348,7 +468,14 @@ def is_retry(self, method, status_code, has_retry_after=False): + + def is_exhausted(self): + """ Are we out of retries? """ +- retry_counts = (self.total, self.connect, self.read, self.redirect, self.status) ++ retry_counts = ( ++ self.total, ++ self.connect, ++ self.read, ++ self.redirect, ++ self.status, ++ self.other, ++ ) + retry_counts = list(filter(None, retry_counts)) + if not retry_counts: + return False +@@ -364,7 +491,7 @@ def increment( + _pool=None, + _stacktrace=None, + ): +- """ Return a new Retry object with incremented retry counters. ++ """Return a new Retry object with incremented retry counters. + + :param response: A response object, or None, if the server did not + return a response. +@@ -386,6 +513,7 @@ def increment( + read = self.read + redirect = self.redirect + status_count = self.status ++ other = self.other + cause = "unknown" + status = None + redirect_location = None +@@ -404,6 +532,11 @@ def increment( + elif read is not None: + read -= 1 + ++ elif error: ++ # Other retry? ++ if other is not None: ++ other -= 1 ++ + elif response and response.get_redirect_location(): + # Redirect retry? + if redirect is not None: +@@ -414,7 +547,7 @@ def increment( + + else: + # Incrementing because of a server error like a 500 in +- # status_forcelist and a the given method is in the whitelist ++ # status_forcelist and the given method is in the allowed_methods + cause = ResponseError.GENERIC_ERROR + if response and response.status: + if status_count is not None: +@@ -432,6 +565,7 @@ def increment( + read=read, + redirect=redirect, + status=status_count, ++ other=other, + history=history, + ) + +@@ -448,6 +582,20 @@ def __repr__(self): + "read={self.read}, redirect={self.redirect}, status={self.status})" + ).format(cls=type(self), self=self) + ++ def __getattr__(self, item): ++ if item == "method_whitelist": ++ # TODO: Remove this deprecated alias in v2.0 ++ warnings.warn( ++ "Using 'method_whitelist' with Retry is deprecated and " ++ "will be removed in v2.0. Use 'allowed_methods' instead", ++ DeprecationWarning, ++ ) ++ return self.allowed_methods ++ try: ++ return getattr(super(Retry, self), item) ++ except AttributeError: ++ return getattr(Retry, item) ++ + + # For backwards compatibility (equivalent to pre-v1.9): + Retry.DEFAULT = Retry(3) +diff --git a/src/pip/_vendor/urllib3/util/ssl_.py b/src/pip/_vendor/urllib3/util/ssl_.py +index d3b463d49f..763da82bb6 100644 +--- a/src/pip/_vendor/urllib3/util/ssl_.py ++++ b/src/pip/_vendor/urllib3/util/ssl_.py +@@ -1,21 +1,27 @@ + from __future__ import absolute_import +-import errno +-import warnings ++ + import hmac ++import os + import sys +- ++import warnings + from binascii import hexlify, unhexlify + from hashlib import md5, sha1, sha256 + +-from .url import IPV4_RE, BRACELESS_IPV6_ADDRZ_RE +-from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning ++from ..exceptions import ( ++ InsecurePlatformWarning, ++ ProxySchemeUnsupported, ++ SNIMissingWarning, ++ SSLError, ++) + from ..packages import six +- ++from .url import BRACELESS_IPV6_ADDRZ_RE, IPV4_RE + + SSLContext = None ++SSLTransport = None + HAS_SNI = False + IS_PYOPENSSL = False + IS_SECURETRANSPORT = False ++ALPN_PROTOCOLS = ["http/1.1"] + + # Maps the length of a digest to a possible hash function producing this digest + HASHFUNC_MAP = {32: md5, 40: sha1, 64: sha256} +@@ -29,8 +35,8 @@ def _const_compare_digest_backport(a, b): + Returns True if the digests match, and False otherwise. + """ + result = abs(len(a) - len(b)) +- for l, r in zip(bytearray(a), bytearray(b)): +- result |= l ^ r ++ for left, right in zip(bytearray(a), bytearray(b)): ++ result |= left ^ right + return result == 0 + + +@@ -38,11 +44,21 @@ def _const_compare_digest_backport(a, b): + + try: # Test for SSL features + import ssl +- from ssl import wrap_socket, CERT_REQUIRED ++ from ssl import CERT_REQUIRED, wrap_socket ++except ImportError: ++ pass ++ ++try: + from ssl import HAS_SNI # Has SNI? + except ImportError: + pass + ++try: ++ from .ssltransport import SSLTransport ++except ImportError: ++ pass ++ ++ + try: # Platform-specific: Python 3.6 + from ssl import PROTOCOL_TLS + +@@ -57,12 +73,18 @@ def _const_compare_digest_backport(a, b): + + + try: +- from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION ++ from ssl import OP_NO_COMPRESSION, OP_NO_SSLv2, OP_NO_SSLv3 + except ImportError: + OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000 + OP_NO_COMPRESSION = 0x20000 + + ++try: # OP_NO_TICKET was added in Python 3.6 ++ from ssl import OP_NO_TICKET ++except ImportError: ++ OP_NO_TICKET = 0x4000 ++ ++ + # A secure default. + # Sources for more information on TLS ciphers: + # +@@ -249,7 +271,7 @@ def create_urllib3_context( + ``ssl.CERT_REQUIRED``. + :param options: + Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, +- ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``. ++ ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``, and ``ssl.OP_NO_TICKET``. + :param ciphers: + Which cipher suites to allow the server to select. + :returns: +@@ -272,6 +294,11 @@ def create_urllib3_context( + # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ + # (issue #309) + options |= OP_NO_COMPRESSION ++ # TLSv1.2 only. Unless set explicitly, do not request tickets. ++ # This may save some bandwidth on wire, and although the ticket is encrypted, ++ # there is a risk associated with it being on wire, ++ # if the server is not rotating its ticketing keys properly. ++ options |= OP_NO_TICKET + + context.options |= options + +@@ -293,6 +320,14 @@ def create_urllib3_context( + # We do our own verification, including fingerprints and alternative + # hostnames. So disable it here + context.check_hostname = False ++ ++ # Enable logging of TLS session keys via defacto standard environment variable ++ # 'SSLKEYLOGFILE', if the feature is available (Python 3.8+). Skip empty values. ++ if hasattr(context, "keylog_filename"): ++ sslkeylogfile = os.environ.get("SSLKEYLOGFILE") ++ if sslkeylogfile: ++ context.keylog_filename = sslkeylogfile ++ + return context + + +@@ -309,6 +344,7 @@ def ssl_wrap_socket( + ca_cert_dir=None, + key_password=None, + ca_cert_data=None, ++ tls_in_tls=False, + ): + """ + All arguments except for server_hostname, ssl_context, and ca_cert_dir have +@@ -330,6 +366,8 @@ def ssl_wrap_socket( + :param ca_cert_data: + Optional string containing CA certificates in PEM format suitable for + passing as the cadata parameter to SSLContext.load_verify_locations() ++ :param tls_in_tls: ++ Use SSLTransport to wrap the existing socket. + """ + context = ssl_context + if context is None: +@@ -341,14 +379,8 @@ def ssl_wrap_socket( + if ca_certs or ca_cert_dir or ca_cert_data: + try: + context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data) +- except IOError as e: # Platform-specific: Python 2.7 ++ except (IOError, OSError) as e: + 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 ssl_context is None and hasattr(context, "load_default_certs"): + # try to load OS default certs; works well on Windows (require Python3.4+) +@@ -366,16 +398,21 @@ def ssl_wrap_socket( + else: + context.load_cert_chain(certfile, keyfile, key_password) + ++ try: ++ if hasattr(context, "set_alpn_protocols"): ++ context.set_alpn_protocols(ALPN_PROTOCOLS) ++ except NotImplementedError: ++ pass ++ + # 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: +- if HAS_SNI and server_hostname is not None: +- return context.wrap_socket(sock, server_hostname=server_hostname) +- ++ use_sni_hostname = server_hostname and not is_ipaddress(server_hostname) ++ # SecureTransport uses server_hostname in certificate verification. ++ send_sni = (use_sni_hostname and HAS_SNI) or ( ++ IS_SECURETRANSPORT and server_hostname ++ ) ++ # Do not warn the user if server_hostname is an invalid SNI hostname. ++ if not HAS_SNI and use_sni_hostname: + warnings.warn( + "An HTTPS request has been made, but the SNI (Server Name " + "Indication) extension to TLS is not available on this platform. " +@@ -387,7 +424,13 @@ def ssl_wrap_socket( + SNIMissingWarning, + ) + +- return context.wrap_socket(sock) ++ if send_sni: ++ ssl_sock = _ssl_wrap_socket_impl( ++ sock, context, tls_in_tls, server_hostname=server_hostname ++ ) ++ else: ++ ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls) ++ return ssl_sock + + + def is_ipaddress(hostname): +@@ -412,3 +455,20 @@ def _is_key_file_encrypted(key_file): + return True + + return False ++ ++ ++def _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname=None): ++ if tls_in_tls: ++ if not SSLTransport: ++ # Import error, ssl is not available. ++ raise ProxySchemeUnsupported( ++ "TLS in TLS requires support for the 'ssl' module" ++ ) ++ ++ SSLTransport._validate_ssl_context_for_tls_in_tls(ssl_context) ++ return SSLTransport(sock, ssl_context, server_hostname) ++ ++ if server_hostname: ++ return ssl_context.wrap_socket(sock, server_hostname=server_hostname) ++ else: ++ return ssl_context.wrap_socket(sock) +diff --git a/src/pip/_vendor/urllib3/util/ssltransport.py b/src/pip/_vendor/urllib3/util/ssltransport.py +new file mode 100644 +index 0000000000..ca00233c93 +--- /dev/null ++++ b/src/pip/_vendor/urllib3/util/ssltransport.py +@@ -0,0 +1,221 @@ ++import io ++import socket ++import ssl ++ ++from pip._vendor.urllib3.exceptions import ProxySchemeUnsupported ++from pip._vendor.urllib3.packages import six ++ ++SSL_BLOCKSIZE = 16384 ++ ++ ++class SSLTransport: ++ """ ++ The SSLTransport wraps an existing socket and establishes an SSL connection. ++ ++ Contrary to Python's implementation of SSLSocket, it allows you to chain ++ multiple TLS connections together. It's particularly useful if you need to ++ implement TLS within TLS. ++ ++ The class supports most of the socket API operations. ++ """ ++ ++ @staticmethod ++ def _validate_ssl_context_for_tls_in_tls(ssl_context): ++ """ ++ Raises a ProxySchemeUnsupported if the provided ssl_context can't be used ++ for TLS in TLS. ++ ++ The only requirement is that the ssl_context provides the 'wrap_bio' ++ methods. ++ """ ++ ++ if not hasattr(ssl_context, "wrap_bio"): ++ if six.PY2: ++ raise ProxySchemeUnsupported( ++ "TLS in TLS requires SSLContext.wrap_bio() which isn't " ++ "supported on Python 2" ++ ) ++ else: ++ raise ProxySchemeUnsupported( ++ "TLS in TLS requires SSLContext.wrap_bio() which isn't " ++ "available on non-native SSLContext" ++ ) ++ ++ def __init__( ++ self, socket, ssl_context, server_hostname=None, suppress_ragged_eofs=True ++ ): ++ """ ++ Create an SSLTransport around socket using the provided ssl_context. ++ """ ++ self.incoming = ssl.MemoryBIO() ++ self.outgoing = ssl.MemoryBIO() ++ ++ self.suppress_ragged_eofs = suppress_ragged_eofs ++ self.socket = socket ++ ++ self.sslobj = ssl_context.wrap_bio( ++ self.incoming, self.outgoing, server_hostname=server_hostname ++ ) ++ ++ # Perform initial handshake. ++ self._ssl_io_loop(self.sslobj.do_handshake) ++ ++ def __enter__(self): ++ return self ++ ++ def __exit__(self, *_): ++ self.close() ++ ++ def fileno(self): ++ return self.socket.fileno() ++ ++ def read(self, len=1024, buffer=None): ++ return self._wrap_ssl_read(len, buffer) ++ ++ def recv(self, len=1024, flags=0): ++ if flags != 0: ++ raise ValueError("non-zero flags not allowed in calls to recv") ++ return self._wrap_ssl_read(len) ++ ++ def recv_into(self, buffer, nbytes=None, flags=0): ++ if flags != 0: ++ raise ValueError("non-zero flags not allowed in calls to recv_into") ++ if buffer and (nbytes is None): ++ nbytes = len(buffer) ++ elif nbytes is None: ++ nbytes = 1024 ++ return self.read(nbytes, buffer) ++ ++ def sendall(self, data, flags=0): ++ if flags != 0: ++ raise ValueError("non-zero flags not allowed in calls to sendall") ++ count = 0 ++ with memoryview(data) as view, view.cast("B") as byte_view: ++ amount = len(byte_view) ++ while count < amount: ++ v = self.send(byte_view[count:]) ++ count += v ++ ++ def send(self, data, flags=0): ++ if flags != 0: ++ raise ValueError("non-zero flags not allowed in calls to send") ++ response = self._ssl_io_loop(self.sslobj.write, data) ++ return response ++ ++ def makefile( ++ self, mode="r", buffering=None, encoding=None, errors=None, newline=None ++ ): ++ """ ++ Python's httpclient uses makefile and buffered io when reading HTTP ++ messages and we need to support it. ++ ++ This is unfortunately a copy and paste of socket.py makefile with small ++ changes to point to the socket directly. ++ """ ++ if not set(mode) <= {"r", "w", "b"}: ++ raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,)) ++ ++ writing = "w" in mode ++ reading = "r" in mode or not writing ++ assert reading or writing ++ binary = "b" in mode ++ rawmode = "" ++ if reading: ++ rawmode += "r" ++ if writing: ++ rawmode += "w" ++ raw = socket.SocketIO(self, rawmode) ++ self.socket._io_refs += 1 ++ if buffering is None: ++ buffering = -1 ++ if buffering < 0: ++ buffering = io.DEFAULT_BUFFER_SIZE ++ if buffering == 0: ++ if not binary: ++ raise ValueError("unbuffered streams must be binary") ++ return raw ++ if reading and writing: ++ buffer = io.BufferedRWPair(raw, raw, buffering) ++ elif reading: ++ buffer = io.BufferedReader(raw, buffering) ++ else: ++ assert writing ++ buffer = io.BufferedWriter(raw, buffering) ++ if binary: ++ return buffer ++ text = io.TextIOWrapper(buffer, encoding, errors, newline) ++ text.mode = mode ++ return text ++ ++ def unwrap(self): ++ self._ssl_io_loop(self.sslobj.unwrap) ++ ++ def close(self): ++ self.socket.close() ++ ++ def getpeercert(self, binary_form=False): ++ return self.sslobj.getpeercert(binary_form) ++ ++ def version(self): ++ return self.sslobj.version() ++ ++ def cipher(self): ++ return self.sslobj.cipher() ++ ++ def selected_alpn_protocol(self): ++ return self.sslobj.selected_alpn_protocol() ++ ++ def selected_npn_protocol(self): ++ return self.sslobj.selected_npn_protocol() ++ ++ def shared_ciphers(self): ++ return self.sslobj.shared_ciphers() ++ ++ def compression(self): ++ return self.sslobj.compression() ++ ++ def settimeout(self, value): ++ self.socket.settimeout(value) ++ ++ def gettimeout(self): ++ return self.socket.gettimeout() ++ ++ def _decref_socketios(self): ++ self.socket._decref_socketios() ++ ++ def _wrap_ssl_read(self, len, buffer=None): ++ try: ++ return self._ssl_io_loop(self.sslobj.read, len, buffer) ++ except ssl.SSLError as e: ++ if e.errno == ssl.SSL_ERROR_EOF and self.suppress_ragged_eofs: ++ return 0 # eof, return 0. ++ else: ++ raise ++ ++ def _ssl_io_loop(self, func, *args): ++ """ Performs an I/O loop between incoming/outgoing and the socket.""" ++ should_loop = True ++ ret = None ++ ++ while should_loop: ++ errno = None ++ try: ++ ret = func(*args) ++ except ssl.SSLError as e: ++ if e.errno not in (ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE): ++ # WANT_READ, and WANT_WRITE are expected, others are not. ++ raise e ++ errno = e.errno ++ ++ buf = self.outgoing.read() ++ self.socket.sendall(buf) ++ ++ if errno is None: ++ should_loop = False ++ elif errno == ssl.SSL_ERROR_WANT_READ: ++ buf = self.socket.recv(SSL_BLOCKSIZE) ++ if buf: ++ self.incoming.write(buf) ++ else: ++ self.incoming.write_eof() ++ return ret +diff --git a/src/pip/_vendor/urllib3/util/timeout.py b/src/pip/_vendor/urllib3/util/timeout.py +index b61fea75c5..ff69593b05 100644 +--- a/src/pip/_vendor/urllib3/util/timeout.py ++++ b/src/pip/_vendor/urllib3/util/timeout.py +@@ -1,9 +1,10 @@ + from __future__ import absolute_import + ++import time ++ + # The default socket timeout, used by httplib to indicate that no timeout was + # specified by the user + from socket import _GLOBAL_DEFAULT_TIMEOUT +-import time + + from ..exceptions import TimeoutStateError + +@@ -17,22 +18,28 @@ + + + class Timeout(object): +- """ Timeout configuration. ++ """Timeout configuration. ++ ++ Timeouts can be defined as a default for a pool: ++ ++ .. code-block:: python ++ ++ timeout = Timeout(connect=2.0, read=7.0) ++ http = PoolManager(timeout=timeout) ++ response = http.request('GET', 'http://example.com/') + +- Timeouts can be defined as a default for a pool:: ++ Or per-request (which overrides the default for the pool): + +- timeout = Timeout(connect=2.0, read=7.0) +- http = PoolManager(timeout=timeout) +- response = http.request('GET', 'http://example.com/') ++ .. code-block:: python + +- Or per-request (which overrides the default for the pool):: ++ response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) + +- response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) ++ Timeouts can be disabled by setting all the parameters to ``None``: + +- Timeouts can be disabled by setting all the parameters to ``None``:: ++ .. code-block:: python + +- no_timeout = Timeout(connect=None, read=None) +- response = http.request('GET', 'http://example.com/, timeout=no_timeout) ++ no_timeout = Timeout(connect=None, read=None) ++ response = http.request('GET', 'http://example.com/, timeout=no_timeout) + + + :param total: +@@ -43,7 +50,7 @@ class Timeout(object): + + Defaults to None. + +- :type total: integer, float, or None ++ :type total: int, float, or None + + :param connect: + The maximum amount of time (in seconds) to wait for a connection +@@ -53,7 +60,7 @@ class Timeout(object): + `_. + None will set an infinite timeout for connection attempts. + +- :type connect: integer, float, or None ++ :type connect: int, float, or None + + :param read: + The maximum amount of time (in seconds) to wait between consecutive +@@ -63,7 +70,7 @@ class Timeout(object): + `_. + None will set an infinite timeout. + +- :type read: integer, float, or None ++ :type read: int, float, or None + + .. note:: + +@@ -111,7 +118,7 @@ def __repr__(self): + + @classmethod + def _validate_timeout(cls, value, name): +- """ Check that a timeout attribute is valid. ++ """Check that a timeout attribute is valid. + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is +@@ -157,7 +164,7 @@ def _validate_timeout(cls, value, name): + + @classmethod + def from_float(cls, timeout): +- """ Create a new Timeout from a legacy timeout value. ++ """Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` +@@ -172,7 +179,7 @@ def from_float(cls, timeout): + return Timeout(read=timeout, connect=timeout) + + def clone(self): +- """ Create a copy of the timeout object ++ """Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. +@@ -186,7 +193,7 @@ def clone(self): + return Timeout(connect=self._connect, read=self._read, total=self.total) + + def start_connect(self): +- """ Start the timeout clock, used during a connect() attempt ++ """Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. +@@ -197,7 +204,7 @@ def start_connect(self): + return self._start_connect + + def get_connect_duration(self): +- """ Gets the time elapsed since the call to :meth:`start_connect`. ++ """Gets the time elapsed since the call to :meth:`start_connect`. + + :return: Elapsed time in seconds. + :rtype: float +@@ -212,7 +219,7 @@ def get_connect_duration(self): + + @property + def connect_timeout(self): +- """ Get the value to use when setting a connection timeout. ++ """Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. +@@ -230,7 +237,7 @@ def connect_timeout(self): + + @property + def read_timeout(self): +- """ Get the value for the read timeout. ++ """Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. +diff --git a/src/pip/_vendor/urllib3/util/url.py b/src/pip/_vendor/urllib3/util/url.py +index 0eb0b6a8cc..66c8795b11 100644 +--- a/src/pip/_vendor/urllib3/util/url.py ++++ b/src/pip/_vendor/urllib3/util/url.py +@@ -1,11 +1,11 @@ + from __future__ import absolute_import ++ + import re + from collections import namedtuple + + from ..exceptions import LocationParseError + from ..packages import six + +- + url_attrs = ["scheme", "auth", "host", "port", "path", "query", "fragment"] + + # We only want to normalize urls with an HTTP(S) scheme. +diff --git a/src/pip/_vendor/urllib3/util/wait.py b/src/pip/_vendor/urllib3/util/wait.py +index d71d2fd722..c280646c7b 100644 +--- a/src/pip/_vendor/urllib3/util/wait.py ++++ b/src/pip/_vendor/urllib3/util/wait.py +@@ -1,7 +1,7 @@ + import errno +-from functools import partial + import select + import sys ++from functools import partial + + try: + from time import monotonic +@@ -140,14 +140,14 @@ def wait_for_socket(*args, **kwargs): + + + def wait_for_read(sock, timeout=None): +- """ Waits for reading to be available on a given socket. ++ """Waits for reading to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, read=True, timeout=timeout) + + + def wait_for_write(sock, timeout=None): +- """ Waits for writing to be available on a given socket. ++ """Waits for writing to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, write=True, timeout=timeout) +diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt +index 06fa1358f0..cc8157f169 100644 +--- a/src/pip/_vendor/vendor.txt ++++ b/src/pip/_vendor/vendor.txt +@@ -1,6 +1,6 @@ + appdirs==1.4.4 + CacheControl==0.12.6 +-colorama==0.4.3 ++colorama==0.4.4 + contextlib2==0.6.0.post1 + distlib==0.3.1 + distro==1.5.0 +@@ -8,17 +8,17 @@ html5lib==1.1 + ipaddress==1.0.23 # Only needed on 2.6 and 2.7 + msgpack==1.0.0 + packaging==20.4 +-pep517==0.8.2 ++pep517==0.9.1 + progress==1.5 + pyparsing==2.4.7 +-requests==2.24.0 +- certifi==2020.06.20 ++requests==2.25.0 ++ certifi==2020.11.08 + chardet==3.0.4 + idna==2.10 +- urllib3==1.25.9 +-resolvelib==0.4.0 ++ urllib3==1.26.2 ++resolvelib==0.5.2 + retrying==1.3.3 + setuptools==44.0.0 + six==1.15.0 +-toml==0.10.1 ++toml==0.10.2 + webencodings==0.5.1 diff --git a/python-pip.spec b/python-pip.spec index 3d035b59a33f24b5c58f6925acf4d9cb6a79f840..d154d8ff80e9f817656e58f7206c6ffc65e889a5 100644 --- a/python-pip.spec +++ b/python-pip.spec @@ -6,7 +6,7 @@ pip is the package installer for Python. You can use pip to install packages fro %global bashcompdir %(b=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null); echo ${b:-%{_sysconfdir}/bash_completion.d}) Name: python-%{srcname} Version: 20.2.2 -Release: 3 +Release: 4 Summary: A tool for installing and managing Python packages License: MIT and Python and ASL 2.0 and BSD and ISC and LGPLv2 and MPLv2.0 and (ASL 2.0 or BSD) URL: http://www.pip-installer.org @@ -16,6 +16,7 @@ Patch1: allow-stripping-given-prefix-from-wheel-RECORD-files.patch Patch2: emit-a-warning-when-running-with-root-privileges.patch Patch3: remove-existing-dist-only-if-path-conflicts.patch Patch6000: dummy-certifi.patch +Patch6001: 396afb118e9a74952ffec21675aff456e10b6579.patch Source10: pip-allow-older-versions.patch %description %{_description} @@ -112,6 +113,9 @@ install -p dist/%{python_wheelname} -t %{buildroot}%{python_wheeldir} %{python_wheeldir}/%{python_wheelname} %changelog +* 20201120213007643685 patch-tracking 20.2.2-4 +- append patch file of upstream repository from <396afb118e9a74952ffec21675aff456e10b6579> to <396afb118e9a74952ffec21675aff456e10b6579> + * Wed Nov 4 2020 wangjie -20.2.2-3 - Type:NA - ID:NA @@ -161,4 +165,4 @@ install -p dist/%{python_wheelname} -t %{buildroot}%{python_wheeldir} - DESC: Synchronize a patch * Mon Sep 23 2019 openEuler Buildteam - 18.0-6 -- Package init +- Package init \ No newline at end of file