diff --git a/news/92.bugfix b/news/92.bugfix new file mode 100644 index 0000000000000000000000000000000000000000..cc65fbaf311feb61149436e9f6fa65b700a49f65 --- /dev/null +++ b/news/92.bugfix @@ -0,0 +1 @@ +Fix an issue of remove command that will unexpectedly uninstall packages in default section. diff --git a/pdm/installers.py b/pdm/installers.py index 3f8b06ee882ed719b2f9598b69483562cf741513..857f345e326449f845d7b68377ffd58d00802f38 100644 --- a/pdm/installers.py +++ b/pdm/installers.py @@ -392,6 +392,7 @@ class Synchronizer: self.candidates = candidates self.environment = environment self.parallel = environment.project.config["parallel_install"] + self.all_candidates = environment.project.get_locked_candidates("__all__") self.working_set = environment.get_working_set() @contextlib.contextmanager @@ -425,15 +426,16 @@ class Synchronizer: candidates = self.candidates.copy() environment = self.environment.marker_environment for key, dist in working_set.items(): - if key not in candidates: - to_remove.append(key) - else: + if key in candidates: can = candidates.pop(key) if can.marker and not can.marker.evaluate(environment): to_remove.append(key) elif not _is_dist_editable(dist) and dist.version != can.version: # XXX: An editable distribution is always considered as consistent. to_update.append(key) + elif key not in self.all_candidates: + # Remove package only if it is not required by any section + to_remove.append(key) to_add = list( { strip_extras(name)[0] diff --git a/tests/cli/test_actions.py b/tests/cli/test_actions.py index b38a9e3129ed19bdf972e33ba1fce22ec1245080..2dbe2f87635236aaa79d0221415e8d52ce74263e 100644 --- a/tests/cli/test_actions.py +++ b/tests/cli/test_actions.py @@ -277,6 +277,15 @@ def test_remove_package_not_exist(project, repository, working_set): actions.do_remove(project, sync=False, packages=["django"]) +def test_remove_package_exist_in_multi_section(project, repository, working_set): + actions.do_add(project, packages=["requests"]) + actions.do_add(project, dev=True, packages=["urllib3"]) + actions.do_remove(project, dev=True, packages=["urllib3"]) + assert "urllib3" not in project.tool_settings["dev-dependencies"] + assert "urllib3" in working_set + assert "requests" in working_set + + def test_add_remove_no_package(project, repository): with pytest.raises(PdmUsageError): actions.do_add(project, packages=())