diff --git a/news/5755.bugfix.rst b/news/5755.bugfix.rst new file mode 100644 index 0000000000..6cbf807c8b --- /dev/null +++ b/news/5755.bugfix.rst @@ -0,0 +1 @@ +Fix regression in ``requirements`` command that was causing package installs after upgrade to ``requirementslib==3.0.0``. diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index 49ae42b42b..df39a56353 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -1,5 +1,4 @@ import os -import re import sys from pipenv import environments @@ -23,7 +22,6 @@ upgrade_options, verbose_option, ) -from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category from pipenv.utils.environment import load_dot_env from pipenv.utils.processes import subprocess_run from pipenv.vendor import click @@ -780,40 +778,17 @@ def verify(state): def requirements( state, dev=False, dev_only=False, hash=False, exclude_markers=False, categories="" ): - from pipenv.utils.dependencies import convert_deps_to_pip + from pipenv.routines.requirements import generate_requirements - lockfile = state.project.load_lockfile(expand_env_vars=False) - - for i, package_index in enumerate(lockfile["_meta"]["sources"]): - prefix = "-i" if i == 0 else "--extra-index-url" - echo(" ".join([prefix, package_index["url"]])) - - deps = {} - categories_list = re.split(r", *| ", categories) if categories else [] - - if categories_list: - for category in categories_list: - category = get_lockfile_section_using_pipfile_category(category.strip()) - deps.update(lockfile.get(category, {})) - else: - if dev or dev_only: - deps.update(lockfile["develop"]) - if not dev_only: - deps.update(lockfile["default"]) - - pip_deps = convert_deps_to_pip( - deps, - project=None, - include_index=False, + generate_requirements( + project=state.project, + dev=dev, + dev_only=dev_only, include_hashes=hash, include_markers=not exclude_markers, + categories=categories, ) - for d in pip_deps: - echo(d) - - sys.exit(0) - if __name__ == "__main__": cli() diff --git a/pipenv/routines/requirements.py b/pipenv/routines/requirements.py new file mode 100644 index 0000000000..de48db446d --- /dev/null +++ b/pipenv/routines/requirements.py @@ -0,0 +1,78 @@ +import re +import sys + +from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category +from pipenv.vendor import click + + +def requirements_from_deps(deps, include_hashes=True, include_markers=True): + pip_packages = [] + + for package_name, package_info in deps.items(): + # Handling git repositories + if "git" in package_info: + git = package_info["git"] + ref = package_info.get("ref", "") + extras = ( + "[{}]".format(",".join(package_info.get("extras", []))) + if "extras" in package_info + else "" + ) + pip_package = f"{package_name}{extras} @ git+{git}@{ref}" + else: + # Handling packages with hashes and markers + version = package_info.get("version", "").replace("==", "") + hashes = ( + " --hash={}".format(" --hash=".join(package_info["hashes"])) + if include_hashes and "hashes" in package_info + else "" + ) + markers = ( + "; {}".format(package_info["markers"]) + if include_markers and "markers" in package_info + else "" + ) + pip_package = f"{package_name}=={version}{hashes}{markers}" + + # Append to the list + pip_packages.append(pip_package) + + # pip_packages contains the pip-installable lines + return pip_packages + + +def generate_requirements( + project, + dev=False, + dev_only=False, + include_hashes=False, + include_markers=True, + categories="", +): + lockfile = project.load_lockfile(expand_env_vars=False) + + for i, package_index in enumerate(lockfile["_meta"]["sources"]): + prefix = "-i" if i == 0 else "--extra-index-url" + click.echo(" ".join([prefix, package_index["url"]])) + + deps = {} + categories_list = re.split(r", *| ", categories) if categories else [] + + if categories_list: + for category in categories_list: + category = get_lockfile_section_using_pipfile_category(category.strip()) + deps.update(lockfile.get(category, {})) + else: + if dev or dev_only: + deps.update(lockfile["develop"]) + if not dev_only: + deps.update(lockfile["default"]) + + pip_installable_lines = requirements_from_deps( + deps, include_hashes=include_hashes, include_markers=include_markers + ) + + for line in pip_installable_lines: + click.echo(line) + + sys.exit(0) diff --git a/tests/integration/test_requirements.py b/tests/integration/test_requirements.py index fb0a8b0c3b..9ffad56b04 100644 --- a/tests/integration/test_requirements.py +++ b/tests/integration/test_requirements.py @@ -163,7 +163,7 @@ def test_requirements_markers_get_included(pipenv_instance_pypi): c = p.pipenv('requirements') assert c.returncode == 0 - assert f'{package}{version} ; {markers}' in c.stdout + assert f'{package}{version}; {markers}' in c.stdout @pytest.mark.requirements