Repository: pypa/pipenv

Issue:
Requirements output different since 2023.7.1 causing pip install issues
### Issue description

The output of `pipenv requirements --hash` has changed slightly in `2023.7.1` (#5757) and `pip` appears to be sensitive to it in some scenarios, causing `pip` to be unable to install the package(s) from the generated requirements.txt.

Snippet of requirements.txt generated with `2023.6.26`

```
pyzip==0.2.0 ; python_version >= '3.1' --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298
```

Snippet of requirements.txt generated with `2023.7.1` - The hash is now before the marker

```
pyzip==0.2.0 --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298; python_version >= '3.1'
```

### Expected result

- `2023.7.1` generates a requirements.txt as per `2023.6.26`

### Actual result

- `2023.7.1` generates a slightly different requirements.txt

### Steps to replicate
Pip successfully installs the package with the `2023.6.26` requirements.txt:

```
$ pipenv run pip --version
pip 23.1.2

$ cat requirements_2023.6.26.txt
pyzip==0.2.0 ; python_version >= '3.1' --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298

$ pipenv run pip install -r requirements_2023.6.26.txt -t test_dir
Collecting pyzip==0.2.0 (from -r requirements_2023.6.26.txt (line 1))
  Using cached pyzip-0.2.0-py3-none-any.whl
Installing collected packages: pyzip
Successfully installed pyzip-0.2.0
```

Pip fails to install the package with the `2023.7.3` requirements.txt, thinking there is a hash mismatch even though it displays two identical shas:

```
$ pipenv run pip --version
pip 23.1.2

$ cat requirements_2023.7.1.txt
pyzip==0.2.0 --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298; python_version >= '3.1'

$ pipenv run pip install -r requirements_2023.7.1.txt -t test_dir
Collecting pyzip==0.2.0 (from -r requirements_2023.7.1.txt (line 1))
  Using cached pyzip-0.2.0-py3-none-any.whl
  WARNING: The hashes of the source archive found in cache entry don't match, ignoring cached built wheel and re-downloading source.
  Using cached pyzip-0.2.0.tar.gz (6.3 kB)
ERROR: 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.
    pyzip==0.2.0 from https://files.pythonhosted.org/packages/40/72/e29470ecfb5f2bc8cdd2a1b8a6aa14af8d44aa08fe5efa407cd991ce2c64/pyzip-0.2.0.tar.gz (from -r requirements_2023.7.1.txt (line 1)):
        Expected sha256 c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298;
             Got        c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298
```

I will raise a PR with a fix for consideration.


Discussion:

Resolving patch:
diff --git a/pipenv/routines/requirements.py b/pipenv/routines/requirements.py
--- a/pipenv/routines/requirements.py
+++ b/pipenv/routines/requirements.py
@@ -32,7 +32,7 @@ def requirements_from_deps(deps, include_hashes=True, include_markers=True):
                 if include_markers and "markers" in package_info
                 else ""
             )
-            pip_package = f"{package_name}=={version}{hashes}{markers}"
+            pip_package = f"{package_name}=={version}{markers}{hashes}"
 
         # Append to the list
         pip_packages.append(pip_package)


Test patch:
diff --git a/tests/integration/test_requirements.py b/tests/integration/test_requirements.py
--- a/tests/integration/test_requirements.py
+++ b/tests/integration/test_requirements.py
@@ -192,6 +192,33 @@ def test_requirements_markers_get_excluded(pipenv_instance_pypi):
         assert c.returncode == 0
         assert markers not in c.stdout
 
+@pytest.mark.requirements
+def test_requirements_hashes_get_included(pipenv_instance_pypi):
+    package, version, markers = "werkzeug", "==2.1.2", "python_version >= '3.7'"
+    first_hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"
+    second_hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
+    lockfile = {
+        "_meta": {"sources": []},
+        "default": {
+            package: {
+                "hashes": [
+                    first_hash,
+                    second_hash
+                ],
+                "markers": markers,
+                "version": version
+            }
+        },
+        "develop": {}
+    }
+
+    with pipenv_instance_pypi(chdir=True) as p:
+        with open(p.lockfile_path, 'w') as f:
+            json.dump(lockfile, f)
+
+        c = p.pipenv('requirements --hash')
+        assert c.returncode == 0
+        assert f'{package}{version}; {markers} --hash={first_hash} --hash={second_hash}' in c.stdout
 
 def test_requirements_generates_requirements_from_lockfile_without_env_var_expansion(
         pipenv_instance_pypi,