Repository: pypa/pip

Issue:
Pip doesn't detect/tell you when SSL/TLS is missing/outdated
I tried downloading a package from PyPI, blissfully unaware that I was missing an SSL/TLS implementation in my Python build (2.7.9+). Pip said:

```
% pip-2.7 install --user google-api-python-client
Downloading/unpacking google-api-python-client
  Cannot fetch index base URL http://pypi.python.org/simple/
  Could not find any downloads that satisfy the requirement google-api-python-client
No distributions at all found for google-api-python-client
Storing complete log in /Users/skip/.pip/pip.log
```

I can visit http://pypi.python.org/simple/ and see that google-api-python-client is one of the links. Looking at pip.log I see that it's somehow translating "http" into "https":

```
  Could not fetch URL http://pypi.python.org/simple/google-api-python-client/: <urlopen error unknown url type: https>
```

After some head scratching and interaction with the distutils-sig list, someone suggested I update pip. That also failed, but then I got the bright idea to try ensurepip. It gave me the real reason for the problem:

```
% python -m ensurepip
Ignoring ensurepip failure: pip 6.0.6 requires SSL/TLS
```

I picked back through the make output from my Python build and found that compilation of _ssl.c had failed. I can now focus on fixing that problem, but it would have been quite nice if pip had originally told me I lacked SSL/TLS support.



Discussion:
I think that this is a pretty simply thing we can do to help reduce some WTF in an edge case.


Resolving patch:
diff --git a/pip/download.py b/pip/download.py
--- a/pip/download.py
+++ b/pip/download.py
@@ -14,6 +14,12 @@
 import sys
 import tempfile
 
+try:
+    import ssl  # noqa
+    HAS_TLS = True
+except ImportError:
+    HAS_TLS = False
+
 from pip._vendor.six.moves.urllib import parse as urllib_parse
 from pip._vendor.six.moves.urllib import request as urllib_request
 
diff --git a/pip/index.py b/pip/index.py
--- a/pip/index.py
+++ b/pip/index.py
@@ -25,7 +25,7 @@
     DistributionNotFound, BestVersionAlreadyInstalled, InvalidWheelFilename,
     UnsupportedWheel,
 )
-from pip.download import url_to_path, path_to_url
+from pip.download import HAS_TLS, url_to_path, path_to_url
 from pip.models import PyPI
 from pip.wheel import Wheel, wheel_ext
 from pip.pep425tags import supported_tags, supported_tags_noarch, get_platform
@@ -175,6 +175,19 @@ def __init__(self, find_links, index_urls,
         # The Session we'll use to make requests
         self.session = session
 
+        # If we don't have TLS enabled, then WARN if anyplace we're looking
+        # relies on TLS.
+        if not HAS_TLS:
+            for link in itertools.chain(self.index_urls, self.find_links):
+                parsed = urllib_parse.urlparse(link)
+                if parsed.scheme == "https":
+                    logger.warning(
+                        "pip is configured with locations that require "
+                        "TLS/SSL, however the ssl module in Python is not "
+                        "available."
+                    )
+                    break
+
     def add_dependency_links(self, links):
         # # FIXME: this shouldn't be global list this, it should only
         # # apply to requirements of the package that specifies the


Test patch: