Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions pex/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,15 @@ def exec_function(ast, globals_map):
from urllib.request import HTTPBasicAuthHandler as HTTPBasicAuthHandler
from urllib.request import HTTPDigestAuthHandler as HTTPDigestAuthHandler
from urllib.request import HTTPPasswordMgrWithDefaultRealm as HTTPPasswordMgrWithDefaultRealm
from urllib.request import HTTPSHandler as HTTPSHandler

try:
# N.B.: Interpreters built without SSL support (as can happen for e.g. embedded / AOSP
# Python builds) do not define `urllib.request.HTTPSHandler` at all. We don't want a mere
# import of this module to blow up in that case; only code paths that actually need to
# perform an HTTPS fetch should fail (and only then, at the point of use).
from urllib.request import HTTPSHandler as HTTPSHandler
except ImportError:
HTTPSHandler = None # type: ignore[assignment,misc]
from urllib.request import ProxyHandler as ProxyHandler
from urllib.request import Request as Request
from urllib.request import build_opener as build_opener
Expand All @@ -153,11 +161,17 @@ def exec_function(ast, globals_map):
from urllib2 import HTTPDigestAuthHandler as HTTPDigestAuthHandler
from urllib2 import HTTPError as HTTPError
from urllib2 import HTTPPasswordMgrWithDefaultRealm as HTTPPasswordMgrWithDefaultRealm
from urllib2 import HTTPSHandler as HTTPSHandler

try:
from urllib2 import HTTPSHandler as HTTPSHandler
except ImportError:
HTTPSHandler = None # type: ignore[assignment,misc]
from urllib2 import ProxyHandler as ProxyHandler
from urllib2 import Request as Request
from urllib2 import build_opener as build_opener

HAS_SSL = HTTPSHandler is not None

urlparse = _url_parse
url_unquote = _url_unquote
url_unquote_plus = _url_unquote_plus
Expand Down
28 changes: 23 additions & 5 deletions pex/fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from pex.auth import PasswordDatabase, PasswordEntry
from pex.compatibility import (
HAS_SSL,
PY2,
AbstractHTTPHandler,
FileHandler,
Expand All @@ -36,7 +37,7 @@

if TYPE_CHECKING:
from ssl import SSLContext
from typing import Any, BinaryIO, Dict, Iterable, Iterator, Mapping, Optional, Text
from typing import Any, BinaryIO, Dict, Iterable, Iterator, List, Mapping, Optional, Text

import attr # vendor:skip
else:
Expand Down Expand Up @@ -120,7 +121,16 @@ def create_ssl_context(self):
# `from gevent import monkey; monkey.patch_all()` call.
#
# See: https://github.com/pex-tool/pex/issues/2415
import ssl
try:
import ssl
except ImportError as e:
# The interpreter was built without SSL support (as can happen for e.g. embedded /
# AOSP Python builds). We only get here if something actually tries to establish an
# HTTPS connection; a plain import of this module never triggers this.
raise IOError(
"Cannot establish an HTTPS connection: this Python interpreter was built "
"without SSL support ({error}).".format(error=e)
)

ssl_context = ssl.create_default_context(cafile=self.cert)
if self.client_cert:
Expand Down Expand Up @@ -149,7 +159,12 @@ def initialize_ssl_context(network_configuration=None):
# N.B.: We eagerly initialize an SSLContext for the default case of no CA cert and no client cert.
# When a custom CA cert or client cert or both are configured, that code will need to call
# initialize_ssl_context on its own.
initialize_ssl_context()
#
# This is skipped entirely when the interpreter has no SSL support at all (e.g. some embedded /
# AOSP Python builds): merely importing this module must not require SSL; only actually fetching
# an https:// URL should (and will, lazily, via create_ssl_context above).
if HAS_SSL:
initialize_ssl_context()


class UnixHTTPConnection(HTTPConnection):
Expand Down Expand Up @@ -254,9 +269,12 @@ def __init__(

handlers = [
ProxyHandler(proxies),
HTTPSHandler(context=get_ssl_context(network_configuration=network_configuration)),
UnixHTTPHandler(),
]
] # type: List[Any]
if HAS_SSL:
handlers.append(
HTTPSHandler(context=get_ssl_context(network_configuration=network_configuration))
)
if handle_file_urls:
handlers.append(FileHandler())

Expand Down