Repository: pypa/pipenv

Issue:
Can't lock private pypi packages when connection to https://pypi.org is iffy
At least from my company network, I can't get a reliable connection to https://pypi.org:

```
$ curl https://pypi.org/ 
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to pypi.org:443 
```

This is causing `pipenv lock` to fail with a "Connection reset by peer", when pipenv is trying to grab hashes from the new warehouse API, for our private pypi packages.

##### Describe your environment

1. Mac OS X
1. Python version: 3.6.3
1. Pipenv version: 8.3.2

##### Expected result

I expect the lock to skip failed hash grabbing.

##### Actual result
```
. . .
Result of round 6: stable, done
Traceback (most recent call last):
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 850, in _validate_conn
    conn.connect()
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connection.py", line 326, in connect
    ssl_context=context)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 329, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 814, in __init__
    self.do_handshake()
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 1068, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [Errno 54] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/requests/adapters.py", line 440, in send
    timeout=timeout
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/util/retry.py", line 357, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/packages/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 850, in _validate_conn
    conn.connect()
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/connection.py", line 326, in connect
    ssl_context=context)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 329, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 814, in __init__
    self.do_handshake()
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 1068, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/local/opt/pyenv/versions/3.6.3/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/helder/.local/bin/pipenv", line 11, in <module>
    sys.exit(cli())
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/cli.py", line 2061, in lock
    do_lock(verbose=verbose, clear=clear, pre=pre)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/cli.py", line 1121, in do_lock
    pre=pre
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/pipenv/utils.py", line 496, in resolve_deps
    r = requests.get('https://pypi.org/pypi/{0}/json'.format(name), timeout=10)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/requests/sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/Users/helder/.local/venvs/pipenv/lib/python3.6/site-packages/requests/adapters.py", line 490, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))
```

##### Fix

We can catch connection failures to `https://pypi.org/pypi/{name}/json`, in `resolve_deps()`:

```
index 919f824..6cfcdc1 100644
--- a/pipenv/utils.py
+++ b/pipenv/utils.py
@@ -39 +39 @@ from pip.exceptions import DistributionNotFound
-from requests.exceptions import HTTPError
+from requests.exceptions import HTTPError, ConnectionError
@@ -594 +594 @@ def resolve_deps(deps, which, which_pip, project, sources=None, verbose=False, p
-                except (ValueError, KeyError):
+                except (ValueError, KeyError, ConnectionError):
```



Discussion:
Yep, that is a sensible patch for this. If you'd like to open that as a PR, I'm happy to merge it. Thanks @helderco!

Resolving patch:
diff --git a/pipenv/utils.py b/pipenv/utils.py
--- a/pipenv/utils.py
+++ b/pipenv/utils.py
@@ -36,7 +36,7 @@
 from piptools import logging
 from piptools.exceptions import NoCandidateFound
 from pip.exceptions import DistributionNotFound
-from requests.exceptions import HTTPError
+from requests.exceptions import HTTPError, ConnectionError
 
 from .pep508checker import lookup
 from .environments import SESSION_IS_INTERACTIVE, PIPENV_MAX_ROUNDS, PIPENV_CACHE_DIR
@@ -591,7 +591,7 @@ def resolve_deps(deps, which, which_pip, project, sources=None, verbose=False, p
                     if not collected_hashes:
                         collected_hashes = list(list(resolver.resolve_hashes([result]).items())[0][1])
 
-                except (ValueError, KeyError):
+                except (ValueError, KeyError, ConnectionError):
                     if verbose:
                         print('Error fetching {}'.format(name))
 


Test patch: