From 3034f696d1d679219ef16c0fa53f0e27471622ed Mon Sep 17 00:00:00 2001 From: frostming Date: Mon, 13 Apr 2020 12:58:51 +0800 Subject: [PATCH] ensure setuptools is installed --- pdm/installers/synchronizers.py | 2 +- pdm/models/environment.py | 23 ++++++++++++++--------- tests/cli/test_actions.py | 2 ++ tests/conftest.py | 1 + 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pdm/installers/synchronizers.py b/pdm/installers/synchronizers.py index b78e966c..9389cdd0 100644 --- a/pdm/installers/synchronizers.py +++ b/pdm/installers/synchronizers.py @@ -115,7 +115,7 @@ class Synchronizer: 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 and key != "wheel": + elif key not in self.all_candidates and key not in ("wheel", "setuptools"): # Remove package only if it is not required by any section to_remove.append(key) to_add = list( diff --git a/pdm/models/environment.py b/pdm/models/environment.py index a026bfcb..edad850b 100644 --- a/pdm/models/environment.py +++ b/pdm/models/environment.py @@ -85,7 +85,7 @@ class Environment: """ self.python_requires = project.python_requires self.project = project - self._wheel_ensured = False + self._essential_installed = False @cached_property def python_executable(self) -> str: @@ -315,11 +315,11 @@ class Environment: # Now all source is prepared, build it. if ireq.link.is_wheel: return (self.project.cache("wheels") / ireq.link.filename).as_posix() + self.ensure_essential_packages() if ireq.editable: builder_class = EditableBuilder else: builder_class = WheelBuilder - self.ensure_wheel_package() kwargs["finder"] = finder with builder_class(ireq) as builder, self.activate(True): return builder.build(**kwargs) @@ -347,18 +347,23 @@ class Environment: # Fallback to use shutil.which to find the executable return shutil.which(command, path=os.getenv("PATH")) - def ensure_wheel_package(self) -> None: - """Ensure wheel package is available and install if it isn't.""" + def ensure_essential_packages(self) -> None: + """Ensure wheel and setuptools are available and install if not""" from pdm.installers import Installer from pdm.models.requirements import parse_requirement from pdm.models.candidates import Candidate - if self._wheel_ensured or "wheel" in self.get_working_set(): + if self._essential_installed: return - req = parse_requirement("wheel") - candidate = Candidate(req, self, "wheel") - Installer(self).install(candidate) - self._wheel_ensured = True + installer = Installer(self) + working_set = self.get_working_set() + for package in ("setuptools", "wheel"): + if package in working_set: + continue + req = parse_requirement(package) + candidate = Candidate(req, self, package) + installer.install(candidate) + self._essential_installed = True def update_shebangs(self, new_path: str) -> None: """Update the shebang lines""" diff --git a/tests/cli/test_actions.py b/tests/cli/test_actions.py index 2dbe2f87..b1dc8395 100644 --- a/tests/cli/test_actions.py +++ b/tests/cli/test_actions.py @@ -29,6 +29,8 @@ def test_sync_only_different(project, repository, working_set, capsys): assert "foo" in working_set assert "test-project" in working_set assert working_set["chardet"].version == "3.0.4" + for package in ("wheel", "setuptools"): + assert package in working_set def test_sync_in_sequential_mode(project, repository, working_set, capsys): diff --git a/tests/conftest.py b/tests/conftest.py index 91763c53..0c496a3e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -229,6 +229,7 @@ def working_set(mocker, repository): installer.install.side_effect = install installer.uninstall.side_effect = uninstall mocker.patch("pdm.installers.synchronizers.Installer", return_value=installer) + mocker.patch("pdm.installers.Installer", return_value=installer) yield rv -- GitLab