Repository: pypa/pipenv

Issue:
Attempting to install pytest under Python 2.7.15 and pipenv==2018.11.14 fails to complete with a claimed hash mismatch
### Issue description

Attempting to install ``pytest`` under Python 2.7.15 and ``pipenv==2018.11.14`` fails to complete with a claimed hash mismatch.

### Expected result

``pytest`` should successfully install, as it did under ``pipenv==2018.10.13`` (build log: https://gitlab.com/kfkitsune/pyHIBP/-/jobs/124421196 ).

### Actual result

Full verbose output of a minimized test scenario can be found in the following build log, testing only the issue at hand: https://gitlab.com/kfkitsune/pyHIBP/-/jobs/124421197

```
Exception information:
Traceback (most recent call last):
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/cli/base_command.py", line 143, in main
    status = self.run(options, args)
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/commands/install.py", line 318, in run
    resolver.resolve(requirement_set)
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/resolve.py", line 109, in resolve
    raise hash_errors
HashErrors: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    scandir==1.9.0 from https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz#sha256=44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064 (from -r /tmp/pipenv-7LZzKV-requirements/pipenv-KmrdXf-requirement.txt (line 1)):
        Expected sha256 f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd
             Got        44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064
Traceback (most recent call last):
  File "/usr/bin/pipenv", line 11, in <module>
    sys.exit(cli())
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pipenv/vendor/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pipenv/cli/command.py", line 249, in install
    editable_packages=state.installstate.editables,
  File "/usr/lib/python2.7/site-packages/pipenv/core.py", line 1872, in do_install
    keep_outdated=keep_outdated
  File "/usr/lib/python2.7/site-packages/pipenv/core.py", line 1232, in do_init
    pypi_mirror=pypi_mirror,
  File "/usr/lib/python2.7/site-packages/pipenv/core.py", line 841, in do_install_dependencies
    retry_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
  File "/usr/lib/python2.7/site-packages/pipenv/core.py", line 748, in batch_install
    _cleanup_procs(procs, not blocking, failed_deps_queue, retry=retry)
  File "/usr/lib/python2.7/site-packages/pipenv/core.py", line 676, in _cleanup_procs
    raise exceptions.InstallError(c.dep.name, extra=err_lines)
pipenv.exceptions.InstallError: ERROR: ERROR: Package installation failed...
```

### Steps to replicate

1) Using Python 2.7.15
2) Install ``pipenv==2018.11.14``.
3) Create a ``Pipfile`` with the following:
```toml
[[source]]

verify_ssl = true
url = "https://pypi.python.org/simple"
name = "pypi"


[packages]

pytest = "*"


[dev-packages]

```
4) Execute: ``pipenv --verbose install --dev``

-------------------------------------------------------------------------------

<details><summary>$ pipenv --support</summary>

Pipenv version: `'2018.11.14'`

Pipenv location: `'/usr/lib/python2.7/site-packages/pipenv'`

Python location: `'/usr/bin/python2'`

Python installations found:

  - `2.7.15`: `/usr/bin/python2.7`

PEP 508 Information:

```
{'implementation_name': 'cpython',
 'implementation_version': '0',
 'os_name': 'posix',
 'platform_machine': 'x86_64',
 'platform_python_implementation': 'CPython',
 'platform_release': '4.14.48-coreos-r2',
 'platform_system': 'Linux',
 'platform_version': '#1 SMP Thu Jun 14 08:23:03 UTC 2018',
 'python_full_version': '2.7.15',
 'python_version': '2.7',
 'sys_platform': 'linux2'}
```

System environment variables:

  - `CI_COMMIT_BEFORE_SHA`
  - `CI_CONFIG_PATH`
  - `CI_PROJECT_NAMESPACE`
  - `CI_BUILD_REF_SLUG`
  - `CI_SERVER_VERSION_PATCH`
  - `CI_SERVER_NAME`
  - `CI_PIPELINE_URL`
  - `CI_PROJECT_PATH_SLUG`
  - `CI_COMMIT_MESSAGE`
  - `CI_COMMIT_REF_SLUG`
  - `CI_PROJECT_VISIBILITY`
  - `CI_REGISTRY_IMAGE`
  - `CI_COMMIT_REF_NAME`
  - `CI_COMMIT_SHA`
  - `PATH`
  - `HOME`
  - `CI_REGISTRY_PASSWORD`
  - `CI_REPOSITORY_URL`
  - `GITLAB_USER_EMAIL`
  - `CI_DISPOSABLE_ENVIRONMENT`
  - `CI_RUNNER_ID`
  - `CI_COMMIT_TITLE`
  - `GITLAB_CI`
  - `CI_SERVER_TLS_CA_FILE`
  - `CI_RUNNER_EXECUTABLE_ARCH`
  - `CI_RUNNER_REVISION`
  - `SHLVL`
  - `CI_BUILD_BEFORE_SHA`
  - `CI_BUILD_REF_NAME`
  - `GITLAB_USER_NAME`
  - `CI_BUILD_ID`
  - `PYTHONFINDER_IGNORE_UNSUPPORTED`
  - `CI_RUNNER_VERSION`
  - `GITLAB_USER_LOGIN`
  - `CI_PROJECT_PATH`
  - `DOCKER_DRIVER`
  - `CI_PROJECT_URL`
  - `CI_JOB_STAGE`
  - `CI_PROJECT_DIR`
  - `CI_BUILD_STAGE`
  - `CI`
  - `GITLAB_USER_ID`
  - `CI_BUILD_REF`
  - `CI_REGISTRY_USER`
  - `CI_SERVER_VERSION`
  - `CI_JOB_NAME`
  - `CI_BUILD_TOKEN`
  - `CI_PROJECT_NAME`
  - `CI_RUNNER_TAGS`
  - `CI_COMMIT_DESCRIPTION`
  - `PYTHONDONTWRITEBYTECODE`
  - `CI_REGISTRY`
  - `PIP_PYTHON_PATH`
  - `CI_JOB_TOKEN`
  - `CI_PROJECT_ID`
  - `CI_PIPELINE_SOURCE`
  - `CI_SERVER_VERSION_MAJOR`
  - `CI_PIPELINE_ID`
  - `CI_SERVER_VERSION_MINOR`
  - `CI_SERVER_REVISION`
  - `PIP_DISABLE_PIP_VERSION_CHECK`
  - `OLDPWD`
  - `HOSTNAME`
  - `CI_JOB_URL`
  - `CI_NODE_TOTAL`
  - `PIPENV_CACHE_DIR`
  - `CI_BUILD_NAME`
  - `PIP_CACHE_DIR`
  - `PWD`
  - `CI_JOB_ID`
  - `PIP_SHIMS_BASE_MODULE`
  - `CI_SERVER`
  - `CI_PIPELINE_IID`
  - `CI_RUNNER_DESCRIPTION`
  - `GITLAB_FEATURES`
  - `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`

Pipenv–specific environment variables:

 - `PIPENV_CACHE_DIR`: `/builds/kfkitsune/pyHIBP/.cache`

Debug–specific environment variables:

  - `PATH`: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`
  - `PWD`: `/builds/kfkitsune/pyHIBP`


---------------------------

Contents of `Pipfile` ('/builds/kfkitsune/pyHIBP/Pipfile'):

```toml
[[source]]

verify_ssl = true
url = "https://pypi.python.org/simple"
name = "pypi"


[packages]

pytest = "*"


[dev-packages]

```

</details>

### Observation

I did take the initiative to compare the SHA-256 value of [scandir==1.9.0](https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz) as it is on PyPI, and the SHA-256 hash of the file downloaded locally matches that provided by the SHA-256 link on the download page. So I believe it is reasonable to state that the file itself is not corrupt.

However, I did notice that pipenv is claiming that it is expecting ``f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd`` as the SHA-256 hash. Looking at the verbose scan log, I do see the following:

```
    Skipping link https://files.pythonhosted.org/packages/9e/a5/56b4dec02b16bb720cac9872fccd63b61a815b70633ef15bfe3ea5ce4488/scandir-1.9.0-cp27-cp27m-win32.whl#sha256=f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd (from https://pypi.org/simple/scandir/); it is not compatible with this Python
    [... lines snipped ...]
    Found link https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz#sha256=44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064 (from https://pypi.org/simple/scandir/), version: 1.9.0
  Using version 1.9.0 (newest of versions: 1.9.0)
  Created temporary directory: /tmp/pip-unpack-BLHSt5
  Looking up "https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz" in the cache
  Current age based on date: 204440
  Ignoring unknown cache-control directive: immutable
  Freshness lifetime from max-age: 365000000
  The response is "fresh", returning cached response
  365000000 > 204440
  Using cached https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz
  Downloading from URL https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz#sha256=44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064 (from https://pypi.org/simple/scandir/)
```

So from the above, we can see that the source tarball is selected for download, and that the claimed SHA-256 hash for the tarball is ``44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064``, which is what pipenv calculated. However, it was expecting ``f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd``, which corresponds to the file ``scandir-1.9.0-cp27-cp27m-win32.whl``. As such, while I cannot speak definitively as I have not dug into the source, what I _believe_ is happening is that pipenv incorrectly selected the hash to compare, while using the correct file for calculation (such as, select the first ``scandir==1.9.0`` file link, and use that SHA hash as the expected hash). Again, I don't know if this is _actually_ what is happening, but based on the way the error presents itself, that is my best speculation.



Discussion:
Is the build running on windows? If the posix style paths are anything to go by, the resolver is correct to skip the `win32` wheel. I can't replicate this in the master branch, but I also can't replicate it with the `2018.11.14` version using the command you provided with the pipfile you provided.  I'm thinking we have this fixed now due to a number of other issues, is there any way you can try with the master branch?

That would be `pip install -e git+https://github.com/pypa/pipenv.git@master#egg=pipenv` at the start of your CI build
Negative, the build is running on Docker with the ``alpine:latest`` image, so the build environment would be Linux. For the rebuild you requested, specifically docker image sha256:196d12cf6ab19273823e700516e98eb1910b03b17840f9d5509f03858484d321 for alpine:latest, according to the CI log.

For clarity, the only reason I even brought up the ``win32`` wheel link was because I noticed that the expected hash was referred to by the link's ``sha256`` parameter, while what was actually downloaded was the source tarball, which had its own hash in the URL. It seemed a little more than mere coincidence, so I felt it best to mention it, in the event it helped to narrow down what might be occurring.

As per your request, I reran the CI build, substituting for ``pipenv/master`` with the command you provided, and the build failed. Full build log: https://gitlab.com/kfkitsune/pyHIBP/-/jobs/124465524

Output from ``pipenv --support``:

<details><summary>$ pipenv --support</summary>

Pipenv version: `'2018.11.15.dev0'`

Pipenv location: `'/builds/kfkitsune/pyHIBP/src/pipenv/pipenv'`

Python location: `'/usr/bin/python2'`

Python installations found:

  - `2.7.15`: `/usr/bin/python2.7`

PEP 508 Information:

```
{'implementation_name': 'cpython',
 'implementation_version': '0',
 'os_name': 'posix',
 'platform_machine': 'x86_64',
 'platform_python_implementation': 'CPython',
 'platform_release': '4.14.48-coreos-r2',
 'platform_system': 'Linux',
 'platform_version': '#1 SMP Thu Jun 14 08:23:03 UTC 2018',
 'python_full_version': '2.7.15',
 'python_version': '2.7',
 'sys_platform': 'linux2'}
```

System environment variables:

  - `CI_COMMIT_BEFORE_SHA`
  - `CI_CONFIG_PATH`
  - `CI_PROJECT_NAMESPACE`
  - `CI_BUILD_REF_SLUG`
  - `CI_SERVER_VERSION_PATCH`
  - `CI_SERVER_NAME`
  - `CI_PIPELINE_URL`
  - `CI_PROJECT_PATH_SLUG`
  - `CI_COMMIT_MESSAGE`
  - `CI_COMMIT_REF_SLUG`
  - `CI_PROJECT_VISIBILITY`
  - `CI_REGISTRY_IMAGE`
  - `CI_COMMIT_REF_NAME`
  - `CI_COMMIT_SHA`
  - `PATH`
  - `HOME`
  - `CI_REGISTRY_PASSWORD`
  - `CI_REPOSITORY_URL`
  - `GITLAB_USER_EMAIL`
  - `CI_DISPOSABLE_ENVIRONMENT`
  - `CI_RUNNER_ID`
  - `CI_COMMIT_TITLE`
  - `GITLAB_CI`
  - `CI_SERVER_TLS_CA_FILE`
  - `CI_RUNNER_EXECUTABLE_ARCH`
  - `CI_RUNNER_REVISION`
  - `SHLVL`
  - `CI_BUILD_BEFORE_SHA`
  - `CI_BUILD_REF_NAME`
  - `GITLAB_USER_NAME`
  - `CI_BUILD_ID`
  - `PYTHONFINDER_IGNORE_UNSUPPORTED`
  - `CI_RUNNER_VERSION`
  - `GITLAB_USER_LOGIN`
  - `CI_PROJECT_PATH`
  - `DOCKER_DRIVER`
  - `CI_PROJECT_URL`
  - `CI_JOB_STAGE`
  - `CI_PROJECT_DIR`
  - `CI_BUILD_STAGE`
  - `CI`
  - `GITLAB_USER_ID`
  - `CI_BUILD_REF`
  - `CI_REGISTRY_USER`
  - `CI_SERVER_VERSION`
  - `CI_JOB_NAME`
  - `CI_BUILD_TOKEN`
  - `CI_PROJECT_NAME`
  - `CI_RUNNER_TAGS`
  - `CI_COMMIT_DESCRIPTION`
  - `PYTHONDONTWRITEBYTECODE`
  - `CI_REGISTRY`
  - `PIP_PYTHON_PATH`
  - `CI_JOB_TOKEN`
  - `CI_PROJECT_ID`
  - `CI_PIPELINE_SOURCE`
  - `CI_SERVER_VERSION_MAJOR`
  - `CI_PIPELINE_ID`
  - `CI_SERVER_VERSION_MINOR`
  - `CI_SERVER_REVISION`
  - `PIP_DISABLE_PIP_VERSION_CHECK`
  - `OLDPWD`
  - `HOSTNAME`
  - `CI_JOB_URL`
  - `CI_NODE_TOTAL`
  - `PIPENV_CACHE_DIR`
  - `CI_BUILD_NAME`
  - `PIP_CACHE_DIR`
  - `PWD`
  - `CI_JOB_ID`
  - `PIP_SHIMS_BASE_MODULE`
  - `CI_SERVER`
  - `CI_PIPELINE_IID`
  - `CI_RUNNER_DESCRIPTION`
  - `GITLAB_FEATURES`
  - `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`

Pipenv–specific environment variables:

 - `PIPENV_CACHE_DIR`: `/builds/kfkitsune/pyHIBP/.cache`

Debug–specific environment variables:

  - `PATH`: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`
  - `PWD`: `/builds/kfkitsune/pyHIBP`


---------------------------

Contents of `Pipfile` ('/builds/kfkitsune/pyHIBP/Pipfile'):

```toml
[[source]]

verify_ssl = true
url = "https://pypi.python.org/simple"
name = "pypi"


[packages]

pytest = "*"


[dev-packages]

```
</details>


The failure mode looks to be the same, with pipenv expecting the ``f5c71e29...`` hash, but getting the ``44975e20...`` hash (the full ``--verbose`` output is in the build log, of course):
```
Exception information:
Traceback (most recent call last):
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/cli/base_command.py", line 143, in main
    status = self.run(options, args)
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/commands/install.py", line 318, in run
    resolver.resolve(requirement_set)
  File "/root/.local/share/virtualenvs/pyHIBP-JuzWPqk-/lib/python2.7/site-packages/pip/_internal/resolve.py", line 109, in resolve
    raise hash_errors
HashErrors: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    scandir==1.9.0 from https://files.pythonhosted.org/packages/16/2a/557af1181e6b4e30254d5a6163b18f5053791ca66e251e77ab08887e8fe3/scandir-1.9.0.tar.gz#sha256=44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064 (from -r /tmp/pipenv-jz3KO_-requirements/pipenv-6DTzfE-requirement.txt (line 1)):
        Expected sha256 f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd
             Got        44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064
Traceback (most recent call last):
  File "/usr/bin/pipenv", line 11, in <module>
    load_entry_point('pipenv', 'console_scripts', 'pipenv')()
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/vendor/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/cli/command.py", line 250, in install
    editable_packages=state.installstate.editables,
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/core.py", line 1887, in do_install
    keep_outdated=keep_outdated
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/core.py", line 1246, in do_init
    pypi_mirror=pypi_mirror,
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/core.py", line 852, in do_install_dependencies
    retry_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/core.py", line 756, in batch_install
    _cleanup_procs(procs, not blocking, failed_deps_queue, retry=retry)
  File "/builds/kfkitsune/pyHIBP/src/pipenv/pipenv/core.py", line 681, in _cleanup_procs
    raise exceptions.InstallError(c.dep.name, extra=err_lines)
pipenv.exceptions.InstallError: ERROR: ERROR: Package installation failed...
Running after script...
$ date
Fri Nov 23 08:20:50 UTC 2018
```
Wow. This one is a head scratcher. Thanks for the build logs, that saved a lot of pointless back and forth. I’ll just make an alpine container and see what I can do 

Resolving patch:
diff --git a/pipenv/utils.py b/pipenv/utils.py
--- a/pipenv/utils.py
+++ b/pipenv/utils.py
@@ -19,26 +19,13 @@
 from first import first
 from vistir.misc import fs_str
 
-six.add_move(six.MovedAttribute("Mapping", "collections", "collections.abc"))
-six.add_move(six.MovedAttribute("Sequence", "collections", "collections.abc"))
-from six.moves import Mapping, Sequence
+six.add_move(six.MovedAttribute("Mapping", "collections", "collections.abc"))  # noqa
+six.add_move(six.MovedAttribute("Sequence", "collections", "collections.abc"))  # noqa
+six.add_move(six.MovedAttribute("Set", "collections", "collections.abc"))  # noqa
+from six.moves import Mapping, Sequence, Set
 
 from vistir.compat import ResourceWarning
 
-try:
-    from weakref import finalize
-except ImportError:
-    try:
-        from .vendor.backports.weakref import finalize
-    except ImportError:
-
-        class finalize(object):
-            def __init__(self, *args, **kwargs):
-                logging.warn("weakref.finalize unavailable, not cleaning...")
-
-            def detach(self):
-                return False
-
 
 logging.basicConfig(level=logging.ERROR)
 
@@ -411,40 +398,55 @@ def resolve(self):
             self.resolved_tree.update(results)
             return self.resolved_tree
 
-    def resolve_hashes(self):
-        def _should_include_hash(ireq):
-            from pipenv.vendor.vistir.compat import Path, to_native_string
-            from pipenv.vendor.vistir.path import url_to_path
+    @staticmethod
+    def _should_include_hash(ireq):
+        from pipenv.vendor.vistir.compat import Path, to_native_string
+        from pipenv.vendor.vistir.path import url_to_path
 
-            # We can only hash artifacts.
-            try:
-                if not ireq.link.is_artifact:
-                    return False
-            except AttributeError:
+        # We can only hash artifacts.
+        try:
+            if not ireq.link.is_artifact:
                 return False
+        except AttributeError:
+            return False
 
-            # But we don't want normal pypi artifcats since the normal resolver
-            # handles those
-            if is_pypi_url(ireq.link.url):
-                return False
+        # But we don't want normal pypi artifcats since the normal resolver
+        # handles those
+        if is_pypi_url(ireq.link.url):
+            return False
 
-            # We also don't want to try to hash directories as this will fail
-            # as these are editable deps and are not hashable.
-            if (ireq.link.scheme == "file" and
-                    Path(to_native_string(url_to_path(ireq.link.url))).is_dir()):
-                return False
-            return True
+        # We also don't want to try to hash directories as this will fail
+        # as these are editable deps and are not hashable.
+        if (ireq.link.scheme == "file" and
+                Path(to_native_string(url_to_path(ireq.link.url))).is_dir()):
+            return False
+        return True
 
+    def resolve_hashes(self):
         if self.results is not None:
             resolved_hashes = self.resolver.resolve_hashes(self.results)
             for ireq, ireq_hashes in resolved_hashes.items():
+                # We _ALWAYS MUST PRIORITIZE_ the inclusion of hashes from local sources
+                # PLEASE *DO NOT MODIFY THIS* TO CHECK WHETHER AN IREQ ALREADY HAS A HASH
+                # RESOLVED. The resolver will pull hashes from PyPI and only from PyPI.
+                # The entire purpose of this approach is to include missing hashes.
+                # This fixes a race condition in resolution for missing dependency caches
+                # see pypa/pipenv#3289
+                if self._should_include_hash(ireq) and (
+                    not ireq_hashes or ireq.link.scheme == "file"
+                ):
+                    if not ireq_hashes:
+                        ireq_hashes = set()
+                    new_hashes = self.resolver.repository._hash_cache.get_hash(ireq.link)
+                    add_to_set(ireq_hashes, new_hashes)
+                else:
+                    ireq_hashes = set(ireq_hashes)
+                # The _ONLY CASE_ where we flat out set the value is if it isn't present
+                # It's a set, so otherwise we *always* need to do a union update
                 if ireq not in self.hashes:
-                    if _should_include_hash(ireq):
-                        self.hashes[ireq] = [
-                            self.resolver.repository._hash_cache.get_hash(ireq.link)
-                        ]
-                    else:
-                        self.hashes[ireq] = ireq_hashes
+                    self.hashes[ireq] = ireq_hashes
+                else:
+                    self.hashes[ireq] |= ireq_hashes
             return self.hashes
 
 
@@ -1485,3 +1487,15 @@ def sys_version(version_tuple):
     sys.version_info = version_tuple
     yield
     sys.version_info = old_version
+
+
+def add_to_set(original_set, element):
+    """Given a set and some arbitrary element, add the element(s) to the set"""
+    if not element:
+        return original_set
+    if isinstance(element, Set):
+        original_set |= element
+    elif isinstance(element, (list, tuple)):
+        original_set |= set(element)
+    else:
+        original_set.add(element)


Test patch:
diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py
--- a/tests/integration/test_lock.py
+++ b/tests/integration/test_lock.py
@@ -1,5 +1,6 @@
 import pytest
 import os
+import sys
 
 from pipenv.utils import temp_environ
 
@@ -517,3 +518,25 @@ def test_lock_no_warnings(PipenvInstance, pypi):
         assert "Warning" in c.err
         assert "Warning" not in c.out
         assert "hello" in c.out
+
+
+@pytest.mark.lock
+@pytest.mark.install
+@pytest.mark.skipif(sys.version_info >= (3, 5), reason="scandir doesn't get installed on python 3.5+")
+def test_lock_missing_cache_entries_gets_all_hashes(monkeypatch, PipenvInstance, pypi, tmpdir):
+    """
+    Test locking pathlib2 on python2.7 which needs `scandir`, but fails to resolve when
+    using a fresh dependency cache.
+    """
+
+    with monkeypatch.context() as m:
+        monkeypatch.setattr("pipenv.patched.piptools.locations.CACHE_DIR", tmpdir.strpath)
+        with PipenvInstance(pypi=pypi, chdir=True) as p:
+            p._pipfile.add("pathlib2", "*")
+            assert "pathlib2" in p.pipfile["packages"]
+            c = p.pipenv("install")
+            assert c.return_code == 0, c.err
+            assert "pathlib2" in p.lockfile["default"]
+            assert "scandir" in p.lockfile["default"]
+            assert isinstance(p.lockfile["default"]["scandir"]["hashes"], list)
+            assert len(p.lockfile["default"]["scandir"]["hashes"]) > 1
diff --git a/tests/pypi/pathlib2/pathlib2-2.3.2-py2.py3-none-any.whl b/tests/pypi/pathlib2/pathlib2-2.3.2-py2.py3-none-any.whl
new file mode 100644
Binary files /dev/null and b/tests/pypi/pathlib2/pathlib2-2.3.2-py2.py3-none-any.whl differ
diff --git a/tests/pypi/pathlib2/pathlib2-2.3.2.tar.gz b/tests/pypi/pathlib2/pathlib2-2.3.2.tar.gz
new file mode 100644
Binary files /dev/null and b/tests/pypi/pathlib2/pathlib2-2.3.2.tar.gz differ
diff --git a/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win32.whl b/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win32.whl
new file mode 100644
Binary files /dev/null and b/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win32.whl differ
diff --git a/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win_amd64.whl b/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win_amd64.whl
new file mode 100644
Binary files /dev/null and b/tests/pypi/scandir/scandir-1.9.0-cp27-cp27m-win_amd64.whl differ
diff --git a/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win32.whl b/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win32.whl
new file mode 100644
Binary files /dev/null and b/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win32.whl differ
diff --git a/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win_amd64.whl b/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win_amd64.whl
new file mode 100644
Binary files /dev/null and b/tests/pypi/scandir/scandir-1.9.0-cp36-cp36m-win_amd64.whl differ
diff --git a/tests/pypi/scandir/scandir-1.9.0.tar.gz b/tests/pypi/scandir/scandir-1.9.0.tar.gz
new file mode 100644
Binary files /dev/null and b/tests/pypi/scandir/scandir-1.9.0.tar.gz differ