From d1fb07eafed98195f420c8b8285b0effd271b5cc Mon Sep 17 00:00:00 2001 From: Andy Kluger Date: Fri, 17 Jan 2020 00:17:54 -0500 Subject: [PATCH] compile: separately handle existing pins marked to-upgrade (-P), and exclude -P args not already pinned or primarily required; fixes #759 Co-Authored-By: Albert Tugushev use long option style --upgrade-package in test exact line-matching in expected output more readable if/else instead of ternary --- piptools/scripts/compile.py | 22 ++++++++++++++-------- tests/test_cli_compile.py | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py index 3e2272a1d..6dcbf4e9b 100755 --- a/piptools/scripts/compile.py +++ b/piptools/scripts/compile.py @@ -282,6 +282,8 @@ def cli( key_from_req(install_req.req): install_req for install_req in upgrade_reqs_gen } + existing_pins_to_upgrade = {} + # Proxy with a LocalRequirementsRepository if --upgrade is not specified # (= default invocation) if not upgrade and os.path.exists(output_file.name): @@ -293,13 +295,14 @@ def cli( ) # Exclude packages from --upgrade-package/-P from the existing - # constraints - existing_pins = { - key_from_req(ireq.req): ireq - for ireq in ireqs - if is_pinned_requirement(ireq) - and key_from_req(ireq.req) not in upgrade_install_reqs - } + # constraints, and separately gather pins to be upgraded + existing_pins = {} + for ireq in filter(is_pinned_requirement, ireqs): + key = key_from_req(ireq.req) + if key in upgrade_install_reqs: + existing_pins_to_upgrade[key] = ireq + else: + existing_pins[key] = ireq repository = LocalRequirementsRepository(existing_pins, repository) ### @@ -345,7 +348,10 @@ def cli( key_from_ireq(ireq) for ireq in constraints if not ireq.constraint } - constraints.extend(upgrade_install_reqs.values()) + allowed_upgrades = primary_packages | set(existing_pins_to_upgrade) + constraints.extend( + ireq for key, ireq in upgrade_install_reqs.items() if key in allowed_upgrades + ) # Filter out pip environment markers which do not match (PEP496) constraints = [ diff --git a/tests/test_cli_compile.py b/tests/test_cli_compile.py index b876bdfa8..e32e3a321 100644 --- a/tests/test_cli_compile.py +++ b/tests/test_cli_compile.py @@ -370,6 +370,22 @@ def test_upgrade_packages_option(pip_conf, runner): assert "small-fake-b==0.3" in out.stderr +def test_upgrade_packages_option_irrelevant(pip_conf, runner): + """ + piptools ignores --upgrade-package/-P items not already constrained. + """ + with open("requirements.in", "w") as req_in: + req_in.write("small-fake-a") + with open("requirements.txt", "w") as req_in: + req_in.write("small-fake-a==0.1") + + out = runner.invoke(cli, ["--upgrade-package", "small-fake-b"]) + + assert out.exit_code == 0 + assert "small-fake-a==0.1" in out.stderr.splitlines() + assert "small-fake-b==0.3" not in out.stderr + + def test_upgrade_packages_option_no_existing_file(pip_conf, runner): """ piptools respects --upgrade-package/-P inline list when the output file