From 1942484c41f5ecc5de36008c2cb807324a9874c0 Mon Sep 17 00:00:00 2001 From: Richard Frank Date: Fri, 24 Sep 2021 20:03:05 -0400 Subject: [PATCH] Ensure extras are propagated when ireq has a req Fixes https://github.com/jazzband/pip-tools/issues/852 --- piptools/resolver.py | 2 ++ tests/test_resolver.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/piptools/resolver.py b/piptools/resolver.py index 4a475e7d1..c759b0ab0 100644 --- a/piptools/resolver.py +++ b/piptools/resolver.py @@ -79,6 +79,8 @@ def combine_install_requirements( combined_ireq.req.specifier &= ireq.req.specifier combined_ireq.constraint &= ireq.constraint combined_ireq.extras = {*combined_ireq.extras, *ireq.extras} + if combined_ireq.req is not None: + combined_ireq.req.extras = set(combined_ireq.extras) # InstallRequirements objects are assumed to come from only one source, and # so they support only a single comes_from entry. This function breaks this diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 03f6e9d9b..7978fb1f7 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -1,4 +1,5 @@ import pytest +from pip._internal.utils.urls import path_to_url from piptools.exceptions import NoCandidateFound from piptools.resolver import RequirementSummary, combine_install_requirements @@ -299,6 +300,43 @@ def test_combine_install_requirements(repository, from_line): assert str(combined_all.req.specifier) == "<3.2,==3.1.1,>3.0" +def test_combine_install_requirements_extras(repository, from_line, make_package): + """ + Extras should be unioned in combined install requirements + (whether or not InstallRequirement.req is None, and testing either order of the inputs) + """ + with_extra = from_line("edx-opaque-keys[django]==1.0.1") + assert with_extra.req is not None + without_extra = from_line("edx-opaque-keys") + assert without_extra.req is not None + + combined = combine_install_requirements(repository, [without_extra, with_extra]) + assert str(combined) == str(with_extra) + assert combined.extras == with_extra.extras + + combined = combine_install_requirements(repository, [with_extra, without_extra]) + assert str(combined) == str(with_extra) + assert combined.extras == with_extra.extras + + test_package = make_package("test-package", extras_require={"extra": []}) + local_package_with_extra = from_line(f"{test_package}[extra]") + assert local_package_with_extra.req is None + local_package_without_extra = from_line(path_to_url(test_package)) + assert local_package_without_extra.req is None + + combined = combine_install_requirements( + repository, [local_package_without_extra, local_package_with_extra] + ) + assert str(combined) == str(local_package_with_extra) + assert combined.extras == local_package_with_extra.extras + + combined = combine_install_requirements( + repository, [local_package_with_extra, local_package_without_extra] + ) + assert str(combined) == str(local_package_with_extra) + assert combined.extras == local_package_with_extra.extras + + def test_compile_failure_shows_provenance(resolver, from_line): """ Provenance of conflicting dependencies should be printed on failure.