From 0cda3f083874fbe2df8bece472d157997246c492 Mon Sep 17 00:00:00 2001 From: Andy Kluger Date: Mon, 23 Sep 2019 13:52:18 -0400 Subject: [PATCH] Sync: Keep installed deps marked as to_install; Let pip sort it out Fixes #896 By including already-installed matching requirements in the to_install set, dependencies of pinned packages will be installed, after potentially being uninstalled, regardless of environment state at time of sync. The already-installed reqs will still not be reinstalled, thanks to pip's own handling. The resulting state is more consistent, predictable, and practical. Modify tests to expect explicit requirements in the to_install set, to match. --- piptools/sync.py | 5 +---- tests/test_sync.py | 12 ++++++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/piptools/sync.py b/piptools/sync.py index 336b88348..e9a8e2961 100644 --- a/piptools/sync.py +++ b/piptools/sync.py @@ -150,7 +150,6 @@ def diff( """ requirements_lut = {diff_key_from_ireq(r): r for r in compiled_requirements} - satisfied = set() # holds keys to_install = set() # holds InstallRequirement objects to_uninstall = set() # holds keys @@ -159,11 +158,9 @@ def diff( key = key_from_req(dist) if key not in requirements_lut or not requirements_lut[key].match_markers(): to_uninstall.add(key) - elif requirements_lut[key].specifier.contains(dist.version): - satisfied.add(key) for key, requirement in requirements_lut.items(): - if key not in satisfied and requirement.match_markers(): + if requirement.match_markers(): to_install.add(requirement) # Make sure to not uninstall any packages that should be ignored diff --git a/tests/test_sync.py b/tests/test_sync.py index 7bd021433..24e040cc1 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -118,7 +118,7 @@ def test_diff_should_do_nothing(): reqs = [] # no requirements to_install, to_uninstall = diff(reqs, installed) - assert to_install == set() + assert to_install == set(reqs) assert to_uninstall == set() @@ -136,7 +136,7 @@ def test_diff_should_uninstall(fake_dist): reqs = [] to_install, to_uninstall = diff(reqs, installed) - assert to_install == set() + assert to_install == set(reqs) assert to_uninstall == {"django"} # no version spec when uninstalling @@ -200,7 +200,7 @@ def test_diff_leave_packaging_packages_alone(fake_dist, from_line): reqs = [from_line("django==1.7")] to_install, to_uninstall = diff(reqs, installed) - assert to_install == set() + assert to_install == set(reqs) assert to_uninstall == {"first"} @@ -221,7 +221,7 @@ def test_diff_leave_piptools_alone(fake_dist, from_line): reqs = [from_line("django==1.7")] to_install, to_uninstall = diff(reqs, installed) - assert to_install == set() + assert to_install == set(reqs) assert to_uninstall == {"foobar"} @@ -242,12 +242,12 @@ def test_diff_with_editable(fake_dist, from_editable): def test_diff_with_matching_url_versions(fake_dist, from_line): - # if URL version is explicitly provided, use it to avoid reinstalling + # if URL version is explicitly provided, pip itself will avoid reinstalling installed = [fake_dist("example==1.0")] reqs = [from_line("file:///example.zip#egg=example==1.0")] to_install, to_uninstall = diff(reqs, installed) - assert to_install == set() + assert to_install == set(reqs) assert to_uninstall == set()