From 77d58a2395fa9daee75781b5050f028795fcaa58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Sun, 15 Jan 2023 15:36:43 +0100 Subject: [PATCH] installer: remove old installer and config setting `experimental.new-installer` --- CHANGELOG.md | 2 +- docs/configuration.md | 3 - src/poetry/config/config.py | 3 +- src/poetry/console/application.py | 1 - src/poetry/console/commands/config.py | 5 - src/poetry/console/commands/install.py | 4 - src/poetry/console/commands/lock.py | 4 - src/poetry/console/commands/update.py | 5 - src/poetry/installation/base_installer.py | 18 - src/poetry/installation/installer.py | 131 +- src/poetry/installation/noop_installer.py | 37 - src/poetry/installation/pip_installer.py | 292 ---- tests/console/commands/test_add.py | 933 +--------- tests/console/commands/test_config.py | 3 - tests/console/conftest.py | 17 - tests/installation/test_installer.py | 34 +- tests/installation/test_installer_old.py | 1919 --------------------- tests/installation/test_pip_installer.py | 302 ---- 18 files changed, 21 insertions(+), 3692 deletions(-) delete mode 100644 src/poetry/installation/base_installer.py delete mode 100644 src/poetry/installation/noop_installer.py delete mode 100644 src/poetry/installation/pip_installer.py delete mode 100644 tests/installation/test_installer_old.py delete mode 100644 tests/installation/test_pip_installer.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a97e31cbe48..dc70795bd58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -457,7 +457,7 @@ $ poetry cache clear pypi --all - Added in info output to `poetry lock --check` ([#5081](https://github.com/python-poetry/poetry/pull/5081)). - Added new argument `--all` for `poetry env remove` to delete all venv of a project at once ([#3212](https://github.com/python-poetry/poetry/pull/3212)). - Added new argument `--without-urls` for `poetry export` to exclude source repository urls from the exported file ([#4763](https://github.com/python-poetry/poetry/pull/4763)). -- Added a `new installer.max-workers` property to the configuration ([#3516](https://github.com/python-poetry/poetry/pull/3516)). +- Added a new `installer.max-workers` property to the configuration ([#3516](https://github.com/python-poetry/poetry/pull/3516)). - Added experimental option `virtualenvs.prefer-active-python` to detect current activated python ([#4852](https://github.com/python-poetry/poetry/pull/4852)). - Added better windows shell support ([#5053](https://github.com/python-poetry/poetry/pull/5053)). diff --git a/docs/configuration.md b/docs/configuration.md index af537772277..058ed7bcc06 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -208,9 +208,6 @@ specific packages. | `package[,package,..]` | Disallow binary distributions for specified packages only. | {{% note %}} -This configuration is only respected when using the new installer. If you have disabled it please -consider re-enabling it. - As with all configurations described here, this is a user specific configuration. This means that this is not taken into consideration when a lockfile is generated or dependencies are resolved. This is applied only when selecting which distribution for dependency should be installed into a Poetry managed diff --git a/src/poetry/config/config.py b/src/poetry/config/config.py index 7cbcba3fc10..a736f45b280 100644 --- a/src/poetry/config/config.py +++ b/src/poetry/config/config.py @@ -124,7 +124,7 @@ class Config: "prefer-active-python": False, "prompt": "{project_name}-py{python_version}", }, - "experimental": {"new-installer": True, "system-git-client": False}, + "experimental": {"system-git-client": False}, "installer": {"parallel": True, "max-workers": None, "no-binary": None}, } @@ -265,7 +265,6 @@ def _get_normalizer(name: str) -> Callable[[str], Any]: "virtualenvs.options.always-copy", "virtualenvs.options.system-site-packages", "virtualenvs.options.prefer-active-python", - "experimental.new-installer", "experimental.system-git-client", "installer.parallel", }: diff --git a/src/poetry/console/application.py b/src/poetry/console/application.py index 2dd422573fa..527d007ebf6 100644 --- a/src/poetry/console/application.py +++ b/src/poetry/console/application.py @@ -335,7 +335,6 @@ def configure_installer_for_command(command: InstallerCommand, io: IO) -> None: poetry.config, disable_cache=poetry.disable_cache, ) - installer.use_executor(poetry.config.get("experimental.new-installer", False)) command.set_installer(installer) def _load_plugins(self, io: IO | None = None) -> None: diff --git a/src/poetry/console/commands/config.py b/src/poetry/console/commands/config.py index 03773a5ef0d..dc0613ef46d 100644 --- a/src/poetry/console/commands/config.py +++ b/src/poetry/console/commands/config.py @@ -91,11 +91,6 @@ def unique_config_values(self) -> dict[str, tuple[Any, Any, Any]]: boolean_normalizer, False, ), - "experimental.new-installer": ( - boolean_validator, - boolean_normalizer, - True, - ), "experimental.system-git-client": ( boolean_validator, boolean_normalizer, diff --git a/src/poetry/console/commands/install.py b/src/poetry/console/commands/install.py index b499970aac9..7a3abdf690c 100644 --- a/src/poetry/console/commands/install.py +++ b/src/poetry/console/commands/install.py @@ -92,10 +92,6 @@ def handle(self) -> int: from poetry.masonry.builders.editable import EditableBuilder - self.installer.use_executor( - self.poetry.config.get("experimental.new-installer", False) - ) - if self.option("extras") and self.option("all-extras"): self.line_error( "You cannot specify explicit" diff --git a/src/poetry/console/commands/lock.py b/src/poetry/console/commands/lock.py index d1009a265e8..c87f1359dc7 100644 --- a/src/poetry/console/commands/lock.py +++ b/src/poetry/console/commands/lock.py @@ -35,10 +35,6 @@ class LockCommand(InstallerCommand): loggers = ["poetry.repositories.pypi_repository"] def handle(self) -> int: - self.installer.use_executor( - self.poetry.config.get("experimental.new-installer", False) - ) - if self.option("check"): if self.poetry.locker.is_locked() and self.poetry.locker.is_fresh(): self.line("poetry.lock is consistent with pyproject.toml.") diff --git a/src/poetry/console/commands/update.py b/src/poetry/console/commands/update.py index 714a924e5bd..4e97d84796b 100644 --- a/src/poetry/console/commands/update.py +++ b/src/poetry/console/commands/update.py @@ -40,11 +40,6 @@ class UpdateCommand(InstallerCommand): def handle(self) -> int: packages = self.argument("packages") - - self.installer.use_executor( - self.poetry.config.get("experimental.new-installer", False) - ) - if packages: self.installer.whitelist({name: "*" for name in packages}) diff --git a/src/poetry/installation/base_installer.py b/src/poetry/installation/base_installer.py deleted file mode 100644 index 8e1d3197618..00000000000 --- a/src/poetry/installation/base_installer.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - - -if TYPE_CHECKING: - from poetry.core.packages.package import Package - - -class BaseInstaller: - def install(self, package: Package) -> None: - raise NotImplementedError - - def update(self, source: Package, target: Package) -> None: - raise NotImplementedError - - def remove(self, package: Package) -> None: - raise NotImplementedError diff --git a/src/poetry/installation/installer.py b/src/poetry/installation/installer.py index 9b906f7678f..c83551a10b1 100644 --- a/src/poetry/installation/installer.py +++ b/src/poetry/installation/installer.py @@ -9,13 +9,11 @@ from poetry.installation.operations import Install from poetry.installation.operations import Uninstall from poetry.installation.operations import Update -from poetry.installation.pip_installer import PipInstaller from poetry.repositories import Repository from poetry.repositories import RepositoryPool from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.lockfile_repository import LockfileRepository from poetry.utils.extras import get_extra_package_names -from poetry.utils.helpers import pluralize if TYPE_CHECKING: @@ -26,7 +24,6 @@ from poetry.core.packages.project_package import ProjectPackage from poetry.config.config import Config - from poetry.installation.base_installer import BaseInstaller from poetry.installation.operations.operation import Operation from poetry.packages import Locker from poetry.utils.env import Env @@ -71,9 +68,7 @@ def __init__( ) self._executor = executor - self._use_executor = False - self._installer = self._get_installer() if installed is None: installed = self._get_installed() @@ -83,10 +78,6 @@ def __init__( def executor(self) -> Executor: return self._executor - @property - def installer(self) -> BaseInstaller: - return self._installer - def set_package(self, package: ProjectPackage) -> Installer: self._package = package @@ -179,11 +170,6 @@ def extras(self, extras: list[str]) -> Installer: return self - def use_executor(self, use_executor: bool = True) -> Installer: - self._use_executor = use_executor - - return self - def _do_refresh(self) -> int: from poetry.puzzle.solver import Solver @@ -363,119 +349,7 @@ def _write_lock_file(self, repo: LockfileRepository, force: bool = False) -> Non self._io.write_line("Writing lock file") def _execute(self, operations: list[Operation]) -> int: - if self._use_executor: - return self._executor.execute(operations) - - if not operations and (self._execute_operations or self._dry_run): - self._io.write_line("No dependencies to install or update") - - if operations and (self._execute_operations or self._dry_run): - installs = 0 - updates = 0 - uninstalls = 0 - skipped = 0 - for op in operations: - if op.skipped: - skipped += 1 - elif op.job_type == "install": - installs += 1 - elif op.job_type == "update": - updates += 1 - elif op.job_type == "uninstall": - uninstalls += 1 - - self._io.write_line("") - self._io.write("Package operations: ") - self._io.write(f"{installs} install{pluralize(installs)}, ") - self._io.write(f"{updates} update{pluralize(updates)}, ") - self._io.write(f"{uninstalls} removal{pluralize(uninstalls)}") - if skipped and self.is_verbose(): - self._io.write(f", {skipped} skipped") - self._io.write_line("") - - self._io.write_line("") - - for op in operations: - self._execute_operation(op) - - return 0 - - def _execute_operation(self, operation: Operation) -> None: - """ - Execute a given operation. - """ - method = operation.job_type - - getattr(self, f"_execute_{method}")(operation) - - def _execute_install(self, operation: Install) -> None: - target = operation.package - if operation.skipped: - if self.is_verbose() and (self._execute_operations or self.is_dry_run()): - self._io.write_line( - f" - Skipping {target.pretty_name}" - f" ({target.full_pretty_version}) {operation.skip_reason}" - ) - - return - - if self._execute_operations or self.is_dry_run(): - self._io.write_line( - f" - Installing {target.pretty_name}" - f" ({target.full_pretty_version})" - ) - - if not self._execute_operations: - return - - self._installer.install(operation.package) - - def _execute_update(self, operation: Update) -> None: - source = operation.initial_package - target = operation.target_package - - if operation.skipped: - if self.is_verbose() and (self._execute_operations or self.is_dry_run()): - self._io.write_line( - f" - Skipping {target.pretty_name} " - f"({target.full_pretty_version}) {operation.skip_reason}" - ) - - return - - if self._execute_operations or self.is_dry_run(): - self._io.write_line( - f" - Updating {target.pretty_name}" - f" ({source.full_pretty_version} ->" - f" {target.full_pretty_version})" - ) - - if not self._execute_operations: - return - - self._installer.update(source, target) - - def _execute_uninstall(self, operation: Uninstall) -> None: - target = operation.package - if operation.skipped: - if self.is_verbose() and (self._execute_operations or self.is_dry_run()): - self._io.write_line( - f" - Not removing {target.pretty_name}" - f" ({target.pretty_version}) {operation.skip_reason}" - ) - - return - - if self._execute_operations or self.is_dry_run(): - self._io.write_line( - f" - Removing {target.pretty_name}" - f" ({target.pretty_version})" - ) - - if not self._execute_operations: - return - - self._installer.remove(operation.package) + return self._executor.execute(operations) def _populate_lockfile_repo( self, repo: LockfileRepository, ops: Iterable[Operation] @@ -562,8 +436,5 @@ def _get_extra_packages(self, repo: Repository) -> set[NormalizedName]: return get_extra_package_names(repo.packages, extras, self._extras) - def _get_installer(self) -> BaseInstaller: - return PipInstaller(self._env, self._io, self._pool) - def _get_installed(self) -> InstalledRepository: return InstalledRepository.load(self._env) diff --git a/src/poetry/installation/noop_installer.py b/src/poetry/installation/noop_installer.py deleted file mode 100644 index 0a994f1484b..00000000000 --- a/src/poetry/installation/noop_installer.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -from poetry.installation.base_installer import BaseInstaller - - -if TYPE_CHECKING: - from poetry.core.packages.package import Package - - -class NoopInstaller(BaseInstaller): - def __init__(self) -> None: - self._installs: list[Package] = [] - self._updates: list[tuple[Package, Package]] = [] - self._removals: list[Package] = [] - - @property - def installs(self) -> list[Package]: - return self._installs - - @property - def updates(self) -> list[tuple[Package, Package]]: - return self._updates - - @property - def removals(self) -> list[Package]: - return self._removals - - def install(self, package: Package) -> None: - self._installs.append(package) - - def update(self, source: Package, target: Package) -> None: - self._updates.append((source, target)) - - def remove(self, package: Package) -> None: - self._removals.append(package) diff --git a/src/poetry/installation/pip_installer.py b/src/poetry/installation/pip_installer.py deleted file mode 100644 index 60d672abc54..00000000000 --- a/src/poetry/installation/pip_installer.py +++ /dev/null @@ -1,292 +0,0 @@ -from __future__ import annotations - -import contextlib -import os -import tempfile -import urllib.parse - -from pathlib import Path -from subprocess import CalledProcessError -from typing import TYPE_CHECKING -from typing import Any - -from poetry.core.constraints.version import Version -from poetry.core.pyproject.toml import PyProjectTOML - -from poetry.installation.base_installer import BaseInstaller -from poetry.repositories.http_repository import HTTPRepository -from poetry.utils._compat import encode -from poetry.utils.helpers import remove_directory -from poetry.utils.pip import pip_install - - -if TYPE_CHECKING: - from cleo.io.io import IO - from poetry.core.masonry.builders.builder import Builder - from poetry.core.packages.package import Package - - from poetry.repositories.repository_pool import RepositoryPool - from poetry.utils.env import Env - - -class PipInstaller(BaseInstaller): - def __init__(self, env: Env, io: IO, pool: RepositoryPool) -> None: - self._env = env - self._io = io - self._pool = pool - - def install(self, package: Package, update: bool = False) -> None: - if package.source_type == "directory": - self.install_directory(package) - - return - - if package.source_type == "git": - self.install_git(package) - - return - - args = ["install", "--no-deps", "--no-input"] - - if not package.is_direct_origin() and package.source_url: - assert package.source_reference is not None - repository = self._pool.repository(package.source_reference) - parsed = urllib.parse.urlparse(package.source_url) - if parsed.scheme == "http": - assert parsed.hostname is not None - self._io.write_error( - " Installing from unsecure host:" - f" {parsed.hostname}" - ) - args += ["--trusted-host", parsed.hostname] - - if isinstance(repository, HTTPRepository): - certificates = repository.certificates - - if certificates.cert: - args += ["--cert", str(certificates.cert)] - - if parsed.scheme == "https" and not certificates.verify: - assert parsed.hostname is not None - args += ["--trusted-host", parsed.hostname] - - if certificates.client_cert: - args += ["--client-cert", str(certificates.client_cert)] - - index_url = repository.authenticated_url - - args += ["--index-url", index_url] - - if ( - self._pool.has_default() - and repository.name != self._pool.repositories[0].name - ): - first_repository = self._pool.repositories[0] - - if isinstance(first_repository, HTTPRepository): - args += [ - "--extra-index-url", - first_repository.authenticated_url, - ] - - if update: - args.append("-U") - - req: str | list[str] - if package.files and not package.source_url: - # Format as a requirements.txt - # We need to create a requirements.txt file - # for each package in order to check hashes. - # This is far from optimal but we do not have any - # other choice since this is the only way for pip - # to verify hashes. - req = self.create_temporary_requirement(package) - args += ["-r", req] - - try: - self.run(*args) - finally: - os.unlink(req) - else: - req = self.requirement(package) - if not isinstance(req, list): - args.append(req) - else: - args += req - - self.run(*args) - - def update(self, package: Package, target: Package) -> None: - if package.source_type != target.source_type: - # If the source type has changed, we remove the current - # package to avoid perpetual updates in some cases - self.remove(package) - - self.install(target, update=True) - - def remove(self, package: Package) -> None: - try: - self.run("uninstall", package.name, "-y") - except CalledProcessError as e: - if "not installed" in str(e): - return - - raise - - # This is a workaround for https://github.com/pypa/pip/issues/4176 - for nspkg_pth_file in self._env.site_packages.find_distribution_nspkg_pth_files( - distribution_name=package.name - ): - nspkg_pth_file.unlink() - - # If we have a VCS package, remove its source directory - if package.source_type == "git": - src_dir = self._env.path / "src" / package.name - if src_dir.exists(): - remove_directory(src_dir, force=True) - - def run(self, *args: Any, **kwargs: Any) -> int | str: - return self._env.run_pip(*args, **kwargs) - - def requirement(self, package: Package, formatted: bool = False) -> str | list[str]: - if formatted and not package.source_type: - req = f"{package.name}=={package.version}" - for f in package.files: - hash_type = "sha256" - h = f["hash"] - if ":" in h: - hash_type, h = h.split(":") - - req += f" --hash {hash_type}:{h}" - - req += "\n" - - return req - - if package.source_type in ["file", "directory"]: - assert package.source_url is not None - if package.root_dir: - req = (package.root_dir / package.source_url).as_posix() - else: - req = os.path.realpath(package.source_url) - - if package.develop and package.source_type == "directory": - return ["-e", req] - - return req - - if package.source_type == "git": - req = ( - f"git+{package.source_url}@{package.source_reference}" - f"#egg={package.name}" - ) - - if package.source_subdirectory: - req += f"&subdirectory={package.source_subdirectory}" - - if package.develop: - return ["-e", req] - - return req - - if package.source_type == "url": - return f"{package.source_url}#egg={package.name}" - - return f"{package.name}=={package.version}" - - def create_temporary_requirement(self, package: Package) -> str: - fd, name = tempfile.mkstemp("reqs.txt", f"{package.name}-{package.version}") - req = self.requirement(package, formatted=True) - if isinstance(req, list): - req = " ".join(req) - - try: - os.write(fd, encode(req)) - finally: - os.close(fd) - - return name - - def install_directory(self, package: Package) -> str | int: - from cleo.io.null_io import NullIO - - from poetry.factory import Factory - - assert package.source_url is not None - if package.root_dir: - req = package.root_dir / package.source_url - else: - req = Path(package.source_url).resolve(strict=False) - - if package.source_subdirectory: - req /= package.source_subdirectory - - pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) - - package_poetry = None - if pyproject.is_poetry_project(): - with contextlib.suppress(RuntimeError): - package_poetry = Factory().create_poetry(pyproject.file.path.parent) - - if package_poetry is not None: - # Even if there is a build system specified - # some versions of pip (< 19.0.0) don't understand it - # so we need to check the version of pip to know - # if we can rely on the build system - legacy_pip = self._env.pip_version < Version.from_parts(19, 0, 0) - - builder: Builder - if package.develop and not package_poetry.package.build_script: - from poetry.masonry.builders.editable import EditableBuilder - - # This is a Poetry package in editable mode - # we can use the EditableBuilder without going through pip - # to install it, unless it has a build script. - builder = EditableBuilder(package_poetry, self._env, NullIO()) - builder.build() - - return 0 - elif legacy_pip or package_poetry.package.build_script: - from poetry.core.masonry.builders.sdist import SdistBuilder - - # We need to rely on creating a temporary setup.py - # file since the version of pip does not support - # build-systems - # We also need it for non-PEP-517 packages - builder = SdistBuilder(package_poetry) - - with builder.setup_py(): - return pip_install( - path=req, - environment=self._env, - upgrade=True, - editable=package.develop, - ) - - return pip_install( - path=req, environment=self._env, upgrade=True, editable=package.develop - ) - - def install_git(self, package: Package) -> None: - from poetry.core.packages.package import Package - - from poetry.vcs.git import Git - - assert package.source_url is not None - source = Git.clone( - url=package.source_url, - source_root=self._env.path / "src", - revision=package.source_resolved_reference or package.source_reference, - ) - - # Now we just need to install from the source directory - pkg = Package( - name=package.name, - version=package.version, - source_type="directory", - source_url=str(source.path), - source_subdirectory=package.source_subdirectory, - develop=package.develop, - ) - - self.install_directory(pkg) diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 9bc238aeb7a..ac04826d930 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -19,7 +19,6 @@ from cleo.testers.command_tester import CommandTester from pytest_mock import MockerFixture - from poetry.installation.noop_installer import NoopInstaller from poetry.poetry import Poetry from poetry.utils.env import MockEnv from poetry.utils.env import VirtualEnv @@ -48,13 +47,6 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: return command_tester_factory("add") -@pytest.fixture() -def old_tester(tester: CommandTester) -> CommandTester: - tester.command.installer.use_executor(False) - - return tester - - def test_add_no_constraint( app: PoetryTestApplication, repo: TestRepository, tester: CommandTester ): @@ -1193,16 +1185,15 @@ def test_add_with_lock( assert content_hash != app.poetry.locker.lock_data["metadata"]["content-hash"] -def test_add_no_constraint_old_installer( +def test_add_to_section_that_does_no_exist_yet( app: PoetryTestApplication, repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, + tester: CommandTester, ): repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.2.0")) - old_tester.execute("cachy") + tester.execute("cachy --group dev") expected = """\ Using version ^0.2.0 for cachy @@ -1214,59 +1205,31 @@ def test_add_no_constraint_old_installer( Package operations: 1 install, 0 updates, 0 removals - - Installing cachy (0.2.0) + • Installing cachy (0.2.0) """ - assert old_tester.io.fetch_output() == expected + assert tester.io.fetch_output() == expected - assert len(installer.installs) == 1 + assert tester.command.installer.executor.installations_count == 1 content = app.poetry.file.read()["tool"]["poetry"] - assert "cachy" in content["dependencies"] - assert content["dependencies"]["cachy"] == "^0.2.0" - - -def test_add_equal_constraint_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(get_package("cachy", "0.2.0")) - - old_tester.execute("cachy==0.1.0") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing cachy (0.1.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 + assert "cachy" in content["group"]["dev"]["dependencies"] + assert content["group"]["dev"]["dependencies"]["cachy"] == "^0.2.0" -def test_add_greater_constraint_old_installer( +def test_add_preferes_stable_releases( app: PoetryTestApplication, repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, + tester: CommandTester, ): - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(get_package("cachy", "0.2.0")) + repo.add_package(get_package("foo", "1.2.3")) + repo.add_package(get_package("foo", "1.2.4b1")) - old_tester.execute("cachy>=0.1.0") + tester.execute("foo") expected = """\ +Using version ^1.2.3 for foo Updating dependencies Resolving dependencies... @@ -1275,874 +1238,10 @@ def test_add_greater_constraint_old_installer( Package operations: 1 install, 0 updates, 0 removals - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - -@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"]) -def test_add_constraint_with_extras_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, - extra_name: str, -): - cachy1 = get_package("cachy", "0.1.0") - cachy1.extras = {"msgpack": [get_dependency("msgpack-python")]} - msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True) - cachy1.add_dependency(msgpack_dep) - - repo.add_package(get_package("cachy", "0.2.0")) - repo.add_package(cachy1) - repo.add_package(get_package("msgpack-python", "0.5.3")) - - old_tester.execute(f"cachy[{extra_name}]>=0.1.0,<0.2.0") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing msgpack-python (0.5.3) - - Installing cachy (0.1.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - -def test_add_constraint_dependencies_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - cachy2 = get_package("cachy", "0.2.0") - msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6") - cachy2.add_dependency(msgpack_dep) - - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(cachy2) - repo.add_package(get_package("msgpack-python", "0.5.3")) - - old_tester.execute("cachy=0.2.0") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing msgpack-python (0.5.3) - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - -def test_add_git_constraint_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cleo", "0.6.5")) - - old_tester.execute("git+https://github.com/demo/demo.git") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.2 9cf87a2) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == { - "git": "https://github.com/demo/demo.git" - } - - -def test_add_git_constraint_with_poetry_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - - old_tester.execute("git+https://github.com/demo/pyproject-demo.git") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.2 9cf87a2) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - -@pytest.mark.parametrize("extra_name", ["foo", "FOO"]) -def test_add_git_constraint_with_extras_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, - extra_name: str, -): - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cleo", "0.6.5")) - repo.add_package(get_package("tomlkit", "0.5.5")) - - old_tester.execute(f"git+https://github.com/demo/demo.git[{extra_name},bar]") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 4 installs, 0 updates, 0 removals - - - Installing cleo (0.6.5) - - Installing pendulum (1.4.4) - - Installing tomlkit (0.5.5) - - Installing demo (0.1.2 9cf87a2) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 4 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == { - "git": "https://github.com/demo/demo.git", - "extras": [extra_name, "bar"], - } - - -def test_add_git_ssh_constraint_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cleo", "0.6.5")) - - old_tester.execute("git+ssh://git@github.com/demo/demo.git@develop") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.2 9cf87a2) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == { - "git": "ssh://git@github.com/demo/demo.git", - "rev": "develop", - } - - -@pytest.mark.parametrize( - "required_fixtures", - [["git/github.com/demo/demo"]], -) -def test_add_directory_constraint_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cleo", "0.6.5")) - - path = "../git/github.com/demo/demo" - old_tester.execute(f"{path}") - - expected = f"""\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.2 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) + • Installing foo (1.2.3) """ - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == {"path": path} - - -@pytest.mark.parametrize( - "required_fixtures", - [["git/github.com/demo/pyproject-demo"]], -) -def test_add_directory_with_poetry_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - - path = "../git/github.com/demo/pyproject-demo" - old_tester.execute(f"{path}") - - expected = f"""\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.2 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - -@pytest.mark.parametrize( - "required_fixtures", - [["distributions/demo-0.1.0-py2.py3-none-any.whl"]], -) -def test_add_file_constraint_wheel_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - - path = "../distributions/demo-0.1.0-py2.py3-none-any.whl" - old_tester.execute(f"{path}") - - expected = f"""\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.0 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == {"path": path} - - -@pytest.mark.parametrize( - "required_fixtures", - [["distributions/demo-0.1.0.tar.gz"]], -) -def test_add_file_constraint_sdist_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pendulum", "1.4.4")) - - path = "../distributions/demo-0.1.0.tar.gz" - old_tester.execute(f"{path}") - - expected = f"""\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo (0.1.0 {app.poetry.file.parent.joinpath(path).resolve().as_posix()}) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == {"path": path} - - -@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"]) -def test_add_constraint_with_extras_option_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, - extra_name: str, -): - cachy2 = get_package("cachy", "0.2.0") - cachy2.extras = {"msgpack": [get_dependency("msgpack-python")]} - msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True) - cachy2.add_dependency(msgpack_dep) - - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(cachy2) - repo.add_package(get_package("msgpack-python", "0.5.3")) - - old_tester.execute(f"cachy=0.2.0 --extras {extra_name}") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing msgpack-python (0.5.3) - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "cachy" in content["dependencies"] - assert content["dependencies"]["cachy"] == { - "version": "0.2.0", - "extras": [extra_name], - } - - -def test_add_url_constraint_wheel_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - mocker: MockerFixture, - old_tester: CommandTester, -): - p = mocker.patch("pathlib.Path.cwd") - p.return_value = Path(__file__) / ".." - - repo.add_package(get_package("pendulum", "1.4.4")) - - old_tester.execute( - "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" - ) - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 2 installs, 0 updates, 0 removals - - - Installing pendulum (1.4.4) - - Installing demo\ - (0.1.0 https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 2 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == { - "url": "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" - } - - -@pytest.mark.parametrize("extra_name", ["foo", "FOO"]) -def test_add_url_constraint_wheel_with_extras_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, - extra_name: str, -): - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cleo", "0.6.5")) - repo.add_package(get_package("tomlkit", "0.5.5")) - - old_tester.execute( - "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" - f"[{extra_name},bar]" - ) - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 4 installs, 0 updates, 0 removals - - - Installing cleo (0.6.5) - - Installing pendulum (1.4.4) - - Installing tomlkit (0.5.5) - - Installing demo\ - (0.1.0 https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 4 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "demo" in content["dependencies"] - assert content["dependencies"]["demo"] == { - "url": ( - "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" - ), - "extras": [extra_name, "bar"], - } - - -def test_add_constraint_with_python_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - cachy2 = get_package("cachy", "0.2.0") - - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(cachy2) - - old_tester.execute("cachy=0.2.0 --python >=2.7") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "cachy" in content["dependencies"] - assert content["dependencies"]["cachy"] == {"version": "0.2.0", "python": ">=2.7"} - - -def test_add_constraint_with_platform_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - env: MockEnv, - old_tester: CommandTester, -): - platform = sys.platform - env._platform = platform - - cachy2 = get_package("cachy", "0.2.0") - - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(cachy2) - - old_tester.execute(f"cachy=0.2.0 --platform {platform} -vvv") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "cachy" in content["dependencies"] - assert content["dependencies"]["cachy"] == { - "version": "0.2.0", - "platform": platform, - } - - -def test_add_constraint_with_source_old_installer( - app: PoetryTestApplication, - poetry: Poetry, - installer: NoopInstaller, - old_tester: CommandTester, - mocker: MockerFixture, -): - repo = LegacyRepository(name="my-index", url="https://my-index.fake") - repo.add_package(get_package("cachy", "0.2.0")) - mocker.patch.object( - repo, - "_find_packages", - wraps=lambda _, name: [ - Package( - "cachy", - Version.parse("0.2.0"), - source_type="legacy", - source_reference=repo.name, - source_url=repo._url, - yanked=False, - ) - ], - ) - - poetry.pool.add_repository(repo) - - old_tester.execute("cachy=0.2.0 --source my-index") - - expected = """\ - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "cachy" in content["dependencies"] - assert content["dependencies"]["cachy"] == { - "version": "0.2.0", - "source": "my-index", - } - - -def test_add_constraint_with_source_that_does_not_exist_old_installer( - app: PoetryTestApplication, old_tester: CommandTester -): - with pytest.raises(IndexError) as e: - old_tester.execute("foo --source i-dont-exist") - - assert str(e.value) == 'Repository "i-dont-exist" does not exist.' - - -def test_add_constraint_not_found_with_source_old_installer( - app: PoetryTestApplication, - poetry: Poetry, - mocker: MockerFixture, - old_tester: CommandTester, -): - repo = LegacyRepository(name="my-index", url="https://my-index.fake") - mocker.patch.object(repo, "find_packages", return_value=[]) - - poetry.pool.add_repository(repo) - - pypi = poetry.pool.repositories[0] - pypi.add_package(get_package("cachy", "0.2.0")) - - with pytest.raises(ValueError) as e: - old_tester.execute("cachy --source my-index") - - assert str(e.value) == "Could not find a matching version of package cachy" - - -def test_add_to_section_that_does_no_exist_yet_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("cachy", "0.1.0")) - repo.add_package(get_package("cachy", "0.2.0")) - - old_tester.execute("cachy --group dev") - - expected = """\ -Using version ^0.2.0 for cachy - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing cachy (0.2.0) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "cachy" in content["group"]["dev"]["dependencies"] - assert content["group"]["dev"]["dependencies"]["cachy"] == "^0.2.0" - - -def test_add_should_not_select_prereleases_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("pyyaml", "3.13")) - repo.add_package(get_package("pyyaml", "4.2b2")) - - old_tester.execute("pyyaml") - - expected = """\ -Using version ^3.13 for pyyaml - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing pyyaml (3.13) -""" - - assert old_tester.io.fetch_output() == expected - - assert len(installer.installs) == 1 - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "pyyaml" in content["dependencies"] - assert content["dependencies"]["pyyaml"] == "^3.13" - - -def test_add_should_skip_when_adding_existing_package_with_no_constraint_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - content = app.poetry.file.read() - content["tool"]["poetry"]["dependencies"]["foo"] = "^1.0" - app.poetry.file.write(content) - - repo.add_package(get_package("foo", "1.1.2")) - - old_tester.execute("foo") - - expected = """\ -The following packages are already present in the pyproject.toml and will be skipped: - - • foo - -If you want to update it to the latest compatible version,\ - you can use `poetry update package`. -If you prefer to upgrade it to the latest available version,\ - you can use `poetry add package@latest`. -""" - - assert expected in old_tester.io.fetch_output() - - -def test_add_should_work_when_adding_existing_package_with_latest_constraint_old_installer( # noqa: E501 - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - content = app.poetry.file.read() - content["tool"]["poetry"]["dependencies"]["foo"] = "^1.0" - app.poetry.file.write(content) - - repo.add_package(get_package("foo", "1.1.2")) - - old_tester.execute("foo@latest") - - expected = """\ -Using version ^1.1.2 for foo - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing foo (1.1.2) -""" - - assert expected in old_tester.io.fetch_output() - - content = app.poetry.file.read()["tool"]["poetry"] - - assert "foo" in content["dependencies"] - assert content["dependencies"]["foo"] == "^1.1.2" - - -def test_add_chooses_prerelease_if_only_prereleases_are_available_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("foo", "1.2.3b0")) - repo.add_package(get_package("foo", "1.2.3b1")) - - old_tester.execute("foo") - - expected = """\ -Using version ^1.2.3b1 for foo - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing foo (1.2.3b1) -""" - assert expected in old_tester.io.fetch_output() - - -def test_add_preferes_stable_releases_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("foo", "1.2.3")) - repo.add_package(get_package("foo", "1.2.4b1")) - - old_tester.execute("foo") - - expected = """\ -Using version ^1.2.3 for foo - -Updating dependencies -Resolving dependencies... - -Writing lock file - -Package operations: 1 install, 0 updates, 0 removals - - - Installing foo (1.2.3) -""" - - assert expected in old_tester.io.fetch_output() - - -def test_add_with_lock_old_installer( - app: PoetryTestApplication, - repo: TestRepository, - installer: NoopInstaller, - old_tester: CommandTester, -): - repo.add_package(get_package("cachy", "0.2.0")) - - old_tester.execute("cachy --lock") - - expected = """\ -Using version ^0.2.0 for cachy - -Updating dependencies -Resolving dependencies... - -Writing lock file -""" - - assert old_tester.io.fetch_output() == expected + assert expected in tester.io.fetch_output() def test_add_keyboard_interrupt_restore_content( diff --git a/tests/console/commands/test_config.py b/tests/console/commands/test_config.py index 052b726c2fd..e53b55f9eeb 100644 --- a/tests/console/commands/test_config.py +++ b/tests/console/commands/test_config.py @@ -51,7 +51,6 @@ def test_list_displays_default_value_if_not_set( cache_dir = json.dumps(str(config_cache_dir)) venv_path = json.dumps(os.path.join("{cache-dir}", "virtualenvs")) expected = f"""cache-dir = {cache_dir} -experimental.new-installer = true experimental.system-git-client = false installer.max-workers = null installer.no-binary = null @@ -80,7 +79,6 @@ def test_list_displays_set_get_setting( cache_dir = json.dumps(str(config_cache_dir)) venv_path = json.dumps(os.path.join("{cache-dir}", "virtualenvs")) expected = f"""cache-dir = {cache_dir} -experimental.new-installer = true experimental.system-git-client = false installer.max-workers = null installer.no-binary = null @@ -133,7 +131,6 @@ def test_list_displays_set_get_local_setting( cache_dir = json.dumps(str(config_cache_dir)) venv_path = json.dumps(os.path.join("{cache-dir}", "virtualenvs")) expected = f"""cache-dir = {cache_dir} -experimental.new-installer = true experimental.system-git-client = false installer.max-workers = null installer.no-binary = null diff --git a/tests/console/conftest.py b/tests/console/conftest.py index a78ceaa89f9..8805f38169e 100644 --- a/tests/console/conftest.py +++ b/tests/console/conftest.py @@ -12,7 +12,6 @@ from cleo.testers.command_tester import CommandTester from poetry.installation import Installer -from poetry.installation.noop_installer import NoopInstaller from poetry.utils.env import MockEnv from tests.helpers import MOCK_DEFAULT_GIT_REVISION from tests.helpers import PoetryTestApplication @@ -34,11 +33,6 @@ from tests.types import ProjectFactory -@pytest.fixture() -def installer() -> NoopInstaller: - return NoopInstaller() - - @pytest.fixture def env(tmp_dir: str) -> MockEnv: path = Path(tmp_dir) / ".venv" @@ -49,15 +43,10 @@ def env(tmp_dir: str) -> MockEnv: @pytest.fixture(autouse=True) def setup( mocker: MockerFixture, - installer: NoopInstaller, installed: Repository, config: Config, env: MockEnv, ) -> Iterator[None]: - # Set Installer's installer - p = mocker.patch("poetry.installation.installer.Installer._get_installer") - p.return_value = installer - # Do not run pip commands of the executor mocker.patch("poetry.installation.executor.Executor.run_pip") @@ -115,11 +104,6 @@ def app_tester(app: PoetryTestApplication) -> ApplicationTester: return ApplicationTester(app) -@pytest.fixture -def new_installer_disabled(config: Config) -> None: - config.merge({"experimental": {"new-installer": False}}) - - @pytest.fixture() def executor(poetry: Poetry, config: Config, env: MockEnv) -> TestExecutor: return TestExecutor(env, poetry.pool, config, NullIO()) @@ -166,7 +150,6 @@ def _tester( executor=executor or TestExecutor(env, poetry.pool, poetry.config, tester.io), ) - installer.use_executor(True) command.set_installer(installer) return tester diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py index 70761e48ebf..57f11f26639 100644 --- a/tests/installation/test_installer.py +++ b/tests/installation/test_installer.py @@ -21,9 +21,8 @@ from poetry.core.toml.file import TOMLFile from poetry.factory import Factory -from poetry.installation import Installer as BaseInstaller +from poetry.installation import Installer from poetry.installation.executor import Executor as BaseExecutor -from poetry.installation.noop_installer import NoopInstaller from poetry.packages import Locker as BaseLocker from poetry.repositories import Repository from poetry.repositories import RepositoryPool @@ -51,11 +50,6 @@ RESERVED_PACKAGES = ("pip", "setuptools", "wheel") -class Installer(BaseInstaller): - def _get_installer(self) -> NoopInstaller: - return NoopInstaller() - - class Executor(BaseExecutor): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) @@ -187,7 +181,7 @@ def installer( installed: CustomInstalledRepository, config: Config, ) -> Installer: - installer = Installer( + return Installer( NullIO(), env, package, @@ -197,9 +191,6 @@ def installer( installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor(True) - - return installer def fixture(name: str) -> dict: @@ -1961,8 +1952,6 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - installer.update(True) installer.whitelist(["D"]) installer.run() @@ -1996,8 +1985,6 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - package.add_dependency(Factory.create_dependency("poetry", {"version": "^0.12.0"})) installer.update(True) @@ -2025,8 +2012,6 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - installer.update(True) installer.whitelist(["pytest"]) installer.run() @@ -2057,8 +2042,6 @@ def test_installer_required_extras_should_be_installed( installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - package.add_dependency( Factory.create_dependency( "cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]} @@ -2085,8 +2068,6 @@ def test_installer_required_extras_should_be_installed( installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - installer.update(True) installer.run() @@ -2200,8 +2181,6 @@ def test_installer_can_install_dependencies_from_forced_source( installed=installed, executor=Executor(env, pool, config, NullIO()), ) - installer.use_executor() - installer.update(True) installer.run() @@ -2267,7 +2246,6 @@ def test_run_installs_with_same_version_url_files( NullIO(), ), ) - installer.use_executor(True) installer.run() expected = fixture("with-same-version-url-dependencies") @@ -2294,7 +2272,6 @@ def test_installer_uses_prereleases_if_they_are_compatible( installer.run() - del installer.installer.installs[:] locker.locked(True) locker.mock_lock_data(locker.written_data) @@ -2332,8 +2309,6 @@ def test_installer_can_handle_old_lock_files( installed=installed, executor=Executor(MockEnv(), pool, config, NullIO()), ) - installer.use_executor() - installer.run() assert installer.executor.installations_count == 6 @@ -2353,8 +2328,6 @@ def test_installer_can_handle_old_lock_files( NullIO(), ), ) - installer.use_executor() - installer.run() # funcsigs will be added @@ -2375,8 +2348,6 @@ def test_installer_can_handle_old_lock_files( NullIO(), ), ) - installer.use_executor() - installer.run() # colorama will be added @@ -2640,7 +2611,6 @@ def test_installer_distinguishes_locked_packages_by_source( NullIO(), ), ) - installer.use_executor(True) installer.run() # Results of installation are consistent with the platform requirements. diff --git a/tests/installation/test_installer_old.py b/tests/installation/test_installer_old.py deleted file mode 100644 index 2b7bbc22afa..00000000000 --- a/tests/installation/test_installer_old.py +++ /dev/null @@ -1,1919 +0,0 @@ -from __future__ import annotations - -import itertools - -from pathlib import Path -from typing import TYPE_CHECKING - -import pytest - -from cleo.io.null_io import NullIO -from poetry.core.packages.project_package import ProjectPackage -from poetry.core.toml.file import TOMLFile - -from poetry.factory import Factory -from poetry.installation import Installer as BaseInstaller -from poetry.installation.noop_installer import NoopInstaller -from poetry.packages import Locker as BaseLocker -from poetry.repositories import Repository -from poetry.repositories import RepositoryPool -from poetry.repositories.installed_repository import InstalledRepository -from poetry.utils.env import MockEnv -from poetry.utils.env import NullEnv -from tests.helpers import get_dependency -from tests.helpers import get_package -from tests.repositories.test_legacy_repository import ( - MockRepository as MockLegacyRepository, -) -from tests.repositories.test_pypi_repository import MockRepository - - -if TYPE_CHECKING: - from pytest_mock import MockerFixture - - from poetry.utils.env import Env - from tests.conftest import Config - from tests.types import FixtureDirGetter - - -RESERVED_PACKAGES = ("pip", "setuptools", "wheel") - - -class Installer(BaseInstaller): - def _get_installer(self) -> NoopInstaller: - return NoopInstaller() - - -class CustomInstalledRepository(InstalledRepository): - @classmethod - def load( - cls, env: Env, with_dependencies: bool = False - ) -> CustomInstalledRepository: - return cls() - - -class Locker(BaseLocker): - def __init__(self, lock_path: str | Path) -> None: - self._lock = TOMLFile(Path(lock_path).joinpath("poetry.lock")) - self._written_data = None - self._locked = False - self._content_hash = self._get_content_hash() - - @property - def written_data(self) -> dict | None: - return self._written_data - - def set_lock_path(self, lock: str | Path) -> Locker: - self._lock = TOMLFile(Path(lock).joinpath("poetry.lock")) - - return self - - def locked(self, is_locked: bool = True) -> Locker: - self._locked = is_locked - - return self - - def mock_lock_data(self, data: dict) -> None: - self._lock_data = data - - def is_locked(self) -> bool: - return self._locked - - def is_fresh(self) -> bool: - return True - - def _get_content_hash(self) -> str: - return "123456789" - - def _write_lock_data(self, data: dict) -> None: - for package in data["package"]: - python_versions = str(package["python-versions"]) - package["python-versions"] = python_versions - - self._written_data = data - self._lock_data = data - - -@pytest.fixture() -def package() -> ProjectPackage: - p = ProjectPackage("root", "1.0") - p.root_dir = Path.cwd() - - return p - - -@pytest.fixture() -def repo() -> Repository: - return Repository("repo") - - -@pytest.fixture() -def pool(repo: Repository) -> RepositoryPool: - pool = RepositoryPool() - pool.add_repository(repo) - - return pool - - -@pytest.fixture() -def installed() -> CustomInstalledRepository: - return CustomInstalledRepository() - - -@pytest.fixture() -def locker(project_root: Path) -> Locker: - return Locker(lock_path=project_root) - - -@pytest.fixture() -def env(tmp_path: Path) -> NullEnv: - return NullEnv(path=tmp_path) - - -@pytest.fixture() -def installer( - package: ProjectPackage, - pool: RepositoryPool, - locker: Locker, - env: NullEnv, - installed: CustomInstalledRepository, - config: Config, -): - return Installer(NullIO(), env, package, locker, pool, config, installed=installed) - - -def fixture(name: str) -> str: - file = TOMLFile(Path(__file__).parent / "fixtures" / f"{name}.test") - - return file.read() - - -def test_run_no_dependencies(installer: Installer, locker: Locker): - installer.run() - expected = fixture("no-dependencies") - - assert locker.written_data == expected - - -def test_run_with_dependencies( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - repo.add_package(package_a) - repo.add_package(package_b) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - - installer.run() - expected = fixture("with-dependencies") - - assert locker.written_data == expected - - -def test_run_update_after_removing_dependencies( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "B", - "version": "1.1", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "C", - "version": "1.2", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": [], "C": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c = get_package("C", "1.2") - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - - installed.add_package(package_a) - installed.add_package(package_b) - installed.add_package(package_c) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "~1.1")) - - installer.update(True) - installer.run() - expected = fixture("with-dependencies") - - assert locker.written_data == expected - - installs = installer.installer.installs - assert len(installs) == 0 - - updates = installer.installer.updates - assert len(updates) == 0 - - removals = installer.installer.removals - assert len(removals) == 1 - - -def test_run_install_no_group( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "B", - "version": "1.1", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "C", - "version": "1.2", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": [], "C": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c = get_package("C", "1.2") - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - - installed.add_package(package_a) - installed.add_package(package_b) - installed.add_package(package_c) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "~1.1")) - package.add_dependency(Factory.create_dependency("C", "~1.2", groups=["dev"])) - - installer.only_groups([]) - installer.run() - - installs = installer.installer.installs - assert len(installs) == 0 - - updates = installer.installer.updates - assert len(updates) == 0 - - removals = installer.installer.removals - assert len(removals) == 0 - - -@pytest.mark.parametrize( - "managed_reserved_package_names", - itertools.chain( - [()], - itertools.permutations(RESERVED_PACKAGES, 1), - itertools.permutations(RESERVED_PACKAGES, 2), - [RESERVED_PACKAGES], - ), -) -def test_run_install_with_synchronization( - managed_reserved_package_names: tuple[str, ...], - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - package_a = get_package("a", "1.0") - package_b = get_package("b", "1.1") - package_c = get_package("c", "1.2") - package_pip = get_package("pip", "20.0.0") - package_setuptools = get_package("setuptools", "20.0.0") - package_wheel = get_package("wheel", "20.0.0") - - all_packages = [ - package_a, - package_b, - package_c, - package_pip, - package_setuptools, - package_wheel, - ] - - managed_reserved_packages = [ - pkg for pkg in all_packages if pkg.name in managed_reserved_package_names - ] - locked_packages = [package_a, *managed_reserved_packages] - - for pkg in all_packages: - repo.add_package(pkg) - installed.add_package(pkg) - - installed.add_package(package) # Root package never removed. - - package.add_dependency(Factory.create_dependency(package_a.name, package_a.version)) - - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": pkg.name, - "version": pkg.version, - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - } - for pkg in locked_packages - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {pkg.name: [] for pkg in locked_packages}, - }, - } - ) - - installer.requires_synchronization(True) - installer.run() - - installs = installer.installer.installs - assert len(installs) == 0 - - updates = installer.installer.updates - assert len(updates) == 0 - - removals = installer.installer.removals - - expected_removals = { - package_b.name, - package_c.name, - *managed_reserved_package_names, - } - assert {r.name for r in removals} == expected_removals - - -def test_run_whitelist_add( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - } - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_a_new = get_package("A", "1.1") - package_b = get_package("B", "1.1") - repo.add_package(package_a) - repo.add_package(package_a_new) - repo.add_package(package_b) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - - installer.update(True) - installer.whitelist(["B"]) - - installer.run() - expected = fixture("with-dependencies") - - assert locker.written_data == expected - - -def test_run_whitelist_remove( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "B", - "version": "1.1", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - repo.add_package(package_a) - repo.add_package(package_b) - installed.add_package(package_b) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - - installer.update(True) - installer.whitelist(["B"]) - - installer.run() - expected = fixture("remove") - - assert locker.written_data == expected - assert len(installer.installer.installs) == 1 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 1 - - -def test_add_with_sub_dependencies( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c = get_package("C", "1.2") - package_d = get_package("D", "1.3") - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - - package_a.add_dependency(Factory.create_dependency("D", "^1.0")) - package_b.add_dependency(Factory.create_dependency("C", "~1.2")) - - installer.run() - expected = fixture("with-sub-dependencies") - - assert locker.written_data == expected - - -def test_run_with_python_versions( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.python_versions = "~2.7 || ^3.4" - - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c12 = get_package("C", "1.2") - package_c12.python_versions = "~2.7 || ^3.3" - package_c13 = get_package("C", "1.3") - package_c13.python_versions = "~3.3" - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c12) - repo.add_package(package_c13) - - package.add_dependency(Factory.create_dependency("A", "~1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - package.add_dependency(Factory.create_dependency("C", "^1.0")) - - installer.run() - expected = fixture("with-python-versions") - - assert locker.written_data == expected - - -def test_run_with_optional_and_python_restricted_dependencies( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.python_versions = "~2.7 || ^3.4" - - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c12 = get_package("C", "1.2") - package_c13 = get_package("C", "1.3") - package_d = get_package("D", "1.4") - package_c13.add_dependency(Factory.create_dependency("D", "^1.2")) - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c12) - repo.add_package(package_c13) - repo.add_package(package_d) - - package.extras = {"foo": [get_dependency("A", "~1.0")]} - package.add_dependency( - Factory.create_dependency("A", {"version": "~1.0", "optional": True}) - ) - package.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "python": "~2.4"}) - ) - package.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7 || ^3.4"}) - ) - - installer.run() - expected = fixture("with-optional-dependencies") - - assert locker.written_data == expected - - installer = installer.installer - # We should only have 2 installs: - # C,D since python version is not compatible - # with B's python constraint and A is optional - assert len(installer.installs) == 2 - assert installer.installs[0].name == "d" - assert installer.installs[1].name == "c" - - -def test_run_with_optional_and_platform_restricted_dependencies( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - mocker: MockerFixture, -): - mocker.patch("sys.platform", "darwin") - - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_c12 = get_package("C", "1.2") - package_c13 = get_package("C", "1.3") - package_d = get_package("D", "1.4") - package_c13.add_dependency(Factory.create_dependency("D", "^1.2")) - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c12) - repo.add_package(package_c13) - repo.add_package(package_d) - - package.extras = {"foo": [get_dependency("A", "~1.0")]} - package.add_dependency( - Factory.create_dependency("A", {"version": "~1.0", "optional": True}) - ) - package.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "platform": "custom"}) - ) - package.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "platform": "darwin"}) - ) - - installer.run() - expected = fixture("with-platform-dependencies") - - assert locker.written_data == expected - - installer = installer.installer - # We should only have 2 installs: - # C,D since the mocked python version is not compatible - # with B's python constraint and A is optional - assert len(installer.installs) == 2 - assert installer.installs[0].name == "d" - assert installer.installs[1].name == "c" - - -def test_run_with_dependencies_extras( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.0") - package_c = get_package("C", "1.0") - - package_b.extras = {"foo": [get_dependency("C", "^1.0")]} - package_b.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "optional": True}) - ) - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - - package.add_dependency(Factory.create_dependency("A", "^1.0")) - package.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]}) - ) - - installer.run() - expected = fixture("with-dependencies-extras") - - assert locker.written_data == expected - - -def test_run_does_not_install_extras_if_not_requested( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.extras["foo"] = [get_dependency("D")] - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.0") - package_c = get_package("C", "1.0") - package_d = get_package("D", "1.1") - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - package.add_dependency(Factory.create_dependency("A", "^1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - package.add_dependency(Factory.create_dependency("C", "^1.0")) - package.add_dependency( - Factory.create_dependency("D", {"version": "^1.0", "optional": True}) - ) - - installer.run() - expected = fixture("extras") - - # Extras are pinned in lock - assert locker.written_data == expected - - # But should not be installed - installer = installer.installer - assert len(installer.installs) == 3 # A, B, C - - -def test_run_installs_extras_if_requested( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.extras["foo"] = [get_dependency("D")] - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.0") - package_c = get_package("C", "1.0") - package_d = get_package("D", "1.1") - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - package.add_dependency(Factory.create_dependency("A", "^1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - package.add_dependency(Factory.create_dependency("C", "^1.0")) - package.add_dependency( - Factory.create_dependency("D", {"version": "^1.0", "optional": True}) - ) - - installer.extras(["foo"]) - installer.run() - expected = fixture("extras") - - # Extras are pinned in lock - assert locker.written_data == expected - - # But should not be installed - installer = installer.installer - assert len(installer.installs) == 4 # A, B, C, D - - -def test_run_installs_extras_with_deps_if_requested( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.extras["foo"] = [get_dependency("C")] - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.0") - package_c = get_package("C", "1.0") - package_d = get_package("D", "1.1") - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - package.add_dependency(Factory.create_dependency("A", "^1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - package.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "optional": True}) - ) - - package_c.add_dependency(Factory.create_dependency("D", "^1.0")) - - installer.extras(["foo"]) - installer.run() - expected = fixture("extras-with-dependencies") - - # Extras are pinned in lock - assert locker.written_data == expected - - # But should not be installed - installer = installer.installer - assert len(installer.installs) == 4 # A, B, C, D - - -def test_run_installs_extras_with_deps_if_requested_locked( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data(fixture("extras-with-dependencies")) - package.extras["foo"] = [get_dependency("C")] - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.0") - package_c = get_package("C", "1.0") - package_d = get_package("D", "1.1") - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - package.add_dependency(Factory.create_dependency("A", "^1.0")) - package.add_dependency(Factory.create_dependency("B", "^1.0")) - package.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "optional": True}) - ) - - package_c.add_dependency(Factory.create_dependency("D", "^1.0")) - - installer.extras(["foo"]) - installer.run() - - # But should not be installed - installer = installer.installer - assert len(installer.installs) == 4 # A, B, C, D - - -def test_installer_with_pypi_repository( - package: ProjectPackage, - locker: Locker, - installed: CustomInstalledRepository, - config: Config, - env: NullEnv, -): - pool = RepositoryPool() - pool.add_repository(MockRepository()) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - package.add_dependency(Factory.create_dependency("pytest", "^3.5", groups=["dev"])) - installer.run() - - expected = fixture("with-pypi-repository") - - assert expected == locker.written_data - - -def test_run_installs_with_local_file( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - fixture_dir: FixtureDirGetter, -): - file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl") - package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)})) - - repo.add_package(get_package("pendulum", "1.4.4")) - - installer.run() - - expected = fixture("with-file-dependency") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 2 - - -def test_run_installs_wheel_with_no_requires_dist( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - fixture_dir: FixtureDirGetter, -): - file_path = fixture_dir( - "wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl" - ) - package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)})) - - installer.run() - - expected = fixture("with-wheel-dependency-no-requires-dist") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 1 - - -def test_run_installs_with_local_poetry_directory_and_extras( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - tmpdir: Path, - fixture_dir: FixtureDirGetter, -): - file_path = fixture_dir("project_with_extras") - package.add_dependency( - Factory.create_dependency( - "project-with-extras", {"path": str(file_path), "extras": ["extras_a"]} - ) - ) - - repo.add_package(get_package("pendulum", "1.4.4")) - - installer.run() - - expected = fixture("with-directory-dependency-poetry") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 2 - - -def test_run_installs_with_local_poetry_directory_transitive( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - tmpdir: Path, - fixture_dir: FixtureDirGetter, -): - root_dir = fixture_dir("directory") - package.root_dir = root_dir - locker.set_lock_path(root_dir) - directory = root_dir.joinpath("project_with_transitive_directory_dependencies") - package.add_dependency( - Factory.create_dependency( - "project-with-transitive-directory-dependencies", - {"path": str(directory.relative_to(root_dir))}, - root_dir=root_dir, - ) - ) - - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cachy", "0.2.0")) - - installer.run() - - expected = fixture("with-directory-dependency-poetry-transitive") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 6 - - -def test_run_installs_with_local_poetry_file_transitive( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - tmpdir: Path, - fixture_dir: FixtureDirGetter, -): - root_dir = fixture_dir("directory") - package.root_dir = root_dir - locker.set_lock_path(root_dir) - directory = root_dir.joinpath("project_with_transitive_file_dependencies") - package.add_dependency( - Factory.create_dependency( - "project-with-transitive-file-dependencies", - {"path": str(directory.relative_to(fixture_dir("directory")))}, - root_dir=root_dir, - ) - ) - - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cachy", "0.2.0")) - - installer.run() - - expected = fixture("with-file-dependency-transitive") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 4 - - -def test_run_installs_with_local_setuptools_directory( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - tmpdir: Path, - fixture_dir: FixtureDirGetter, -): - file_path = fixture_dir("project_with_setup/") - package.add_dependency( - Factory.create_dependency("project-with-setup", {"path": str(file_path)}) - ) - - repo.add_package(get_package("pendulum", "1.4.4")) - repo.add_package(get_package("cachy", "0.2.0")) - - installer.run() - - expected = fixture("with-directory-dependency-setuptools") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 3 - - -def test_run_with_prereleases( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0a2", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - } - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": []}, - }, - } - ) - package_a = get_package("A", "1.0a2") - package_b = get_package("B", "1.1") - repo.add_package(package_a) - repo.add_package(package_b) - - package.add_dependency( - Factory.create_dependency("A", {"version": "*", "allow-prereleases": True}) - ) - package.add_dependency(Factory.create_dependency("B", "^1.1")) - - installer.update(True) - installer.whitelist({"B": "^1.1"}) - - installer.run() - expected = fixture("with-prereleases") - - assert locker.written_data == expected - - -def test_run_changes_category_if_needed( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "dev", - "optional": True, - "platform": "*", - "python-versions": "*", - "checksum": [], - } - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_b = get_package("B", "1.1") - package_b.add_dependency(Factory.create_dependency("A", "^1.0")) - repo.add_package(package_a) - repo.add_package(package_b) - - package.add_dependency( - Factory.create_dependency( - "A", {"version": "^1.0", "optional": True}, groups=["dev"] - ) - ) - package.add_dependency(Factory.create_dependency("B", "^1.1")) - - installer.update(True) - installer.whitelist(["B"]) - - installer.run() - expected = fixture("with-category-change") - - assert locker.written_data == expected - - -def test_run_update_all_with_lock( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "dev", - "optional": True, - "platform": "*", - "python-versions": "*", - "checksum": [], - } - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": []}, - }, - } - ) - package_a = get_package("A", "1.1") - repo.add_package(get_package("A", "1.0")) - repo.add_package(package_a) - - package.add_dependency(Factory.create_dependency("A", "*")) - - installer.update(True) - - installer.run() - expected = fixture("update-with-lock") - - assert locker.written_data == expected - - -def test_run_update_with_locked_extras( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"B": "^1.0", "C": "^1.0"}, - }, - { - "name": "B", - "version": "1.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "C", - "version": "1.1", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "requirements": {"python": "~2.7"}, - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": [], "C": []}, - }, - } - ) - package_a = get_package("A", "1.0") - package_a.extras["foo"] = [get_dependency("B")] - b_dependency = get_dependency("B", "^1.0", optional=True) - b_dependency.in_extras.append("foo") - c_dependency = get_dependency("C", "^1.0") - c_dependency.python_versions = "~2.7" - package_a.add_dependency(b_dependency) - package_a.add_dependency(c_dependency) - - repo.add_package(package_a) - repo.add_package(get_package("B", "1.0")) - repo.add_package(get_package("C", "1.1")) - repo.add_package(get_package("D", "1.1")) - - package.add_dependency( - Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo"]}) - ) - package.add_dependency(Factory.create_dependency("D", "^1.0")) - - installer.update(True) - installer.whitelist("D") - - installer.run() - expected = fixture("update-with-locked-extras") - - assert locker.written_data == expected - - -def test_run_install_duplicate_dependencies_different_constraints( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - package.add_dependency(Factory.create_dependency("A", "*")) - - package_a = get_package("A", "1.0") - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"}) - ) - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"}) - ) - - package_b10 = get_package("B", "1.0") - package_b20 = get_package("B", "2.0") - package_b10.add_dependency(Factory.create_dependency("C", "1.2")) - package_b20.add_dependency(Factory.create_dependency("C", "1.5")) - - package_c12 = get_package("C", "1.2") - package_c15 = get_package("C", "1.5") - - repo.add_package(package_a) - repo.add_package(package_b10) - repo.add_package(package_b20) - repo.add_package(package_c12) - repo.add_package(package_c15) - - installer.run() - - expected = fixture("with-duplicate-dependencies") - - assert locker.written_data == expected - - installs = installer.installer.installs - assert len(installs) == 3 - assert installs[0] == package_c12 - assert installs[1] == package_b10 - assert installs[2] == package_a - - updates = installer.installer.updates - assert len(updates) == 0 - removals = installer.installer.removals - assert len(removals) == 0 - - -def test_run_install_duplicate_dependencies_different_constraints_with_lock( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": { - "B": [ - {"version": "^1.0", "python": "<4.0"}, - {"version": "^2.0", "python": ">=4.0"}, - ] - }, - }, - { - "name": "B", - "version": "1.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"C": "1.2"}, - "requirements": {"python": "<4.0"}, - }, - { - "name": "B", - "version": "2.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"C": "1.5"}, - "requirements": {"python": ">=4.0"}, - }, - { - "name": "C", - "version": "1.2", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "C", - "version": "1.5", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": [], "C": []}, - }, - } - ) - package.add_dependency(Factory.create_dependency("A", "*")) - - package_a = get_package("A", "1.0") - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"}) - ) - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"}) - ) - - package_b10 = get_package("B", "1.0") - package_b20 = get_package("B", "2.0") - package_b10.add_dependency(Factory.create_dependency("C", "1.2")) - package_b20.add_dependency(Factory.create_dependency("C", "1.5")) - - package_c12 = get_package("C", "1.2") - package_c15 = get_package("C", "1.5") - - repo.add_package(package_a) - repo.add_package(package_b10) - repo.add_package(package_b20) - repo.add_package(package_c12) - repo.add_package(package_c15) - - installer.update(True) - installer.run() - - expected = fixture("with-duplicate-dependencies") - - assert locker.written_data == expected - - installs = installer.installer.installs - assert len(installs) == 3 - updates = installer.installer.updates - assert len(updates) == 0 - removals = installer.installer.removals - assert len(removals) == 0 - - -def test_run_update_uninstalls_after_removal_transient_dependency( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"B": {"version": "^1.0", "python": "<2.0"}}, - }, - { - "name": "B", - "version": "1.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": []}, - }, - } - ) - package.add_dependency(Factory.create_dependency("A", "*")) - - package_a = get_package("A", "1.0") - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"}) - ) - - package_b10 = get_package("B", "1.0") - - repo.add_package(package_a) - repo.add_package(package_b10) - - installed.add_package(get_package("A", "1.0")) - installed.add_package(get_package("B", "1.0")) - - installer.update(True) - installer.run() - - installs = installer.installer.installs - assert len(installs) == 0 - updates = installer.installer.updates - assert len(updates) == 0 - removals = installer.installer.removals - assert len(removals) == 1 - - -def test_run_install_duplicate_dependencies_different_constraints_with_lock_update( - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": { - "B": [ - {"version": "^1.0", "python": "<2.7"}, - {"version": "^2.0", "python": ">=2.7"}, - ] - }, - }, - { - "name": "B", - "version": "1.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"C": "1.2"}, - "requirements": {"python": "<2.7"}, - }, - { - "name": "B", - "version": "2.0", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"C": "1.5"}, - "requirements": {"python": ">=2.7"}, - }, - { - "name": "C", - "version": "1.2", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - { - "name": "C", - "version": "1.5", - "category": "dev", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": [], "C": []}, - }, - } - ) - package.add_dependency(Factory.create_dependency("A", "*")) - - package_a = get_package("A", "1.1") - package_a.add_dependency(Factory.create_dependency("B", "^2.0")) - - package_b10 = get_package("B", "1.0") - package_b20 = get_package("B", "2.0") - package_b10.add_dependency(Factory.create_dependency("C", "1.2")) - package_b20.add_dependency(Factory.create_dependency("C", "1.5")) - - package_c12 = get_package("C", "1.2") - package_c15 = get_package("C", "1.5") - - repo.add_package(package_a) - repo.add_package(package_b10) - repo.add_package(package_b20) - repo.add_package(package_c12) - repo.add_package(package_c15) - - installed.add_package(get_package("A", "1.0")) - - installer.update(True) - installer.whitelist(["A"]) - installer.run() - - expected = fixture("with-duplicate-dependencies-update") - - assert locker.written_data == expected - - installs = installer.installer.installs - assert len(installs) == 2 - updates = installer.installer.updates - assert len(updates) == 1 - removals = installer.installer.removals - assert len(removals) == 0 - - -@pytest.mark.skip( - "This is not working at the moment due to limitations in the resolver" -) -def test_installer_test_solver_finds_compatible_package_for_dependency_python_not_fully_compatible_with_package_python( # noqa: E501 - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, -): - package.python_versions = "~2.7 || ^3.4" - package.add_dependency( - Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"}) - ) - - package_a101 = get_package("A", "1.0.1") - package_a101.python_versions = ">=3.6" - - package_a100 = get_package("A", "1.0.0") - package_a100.python_versions = ">=3.5" - - repo.add_package(package_a100) - repo.add_package(package_a101) - - installer.run() - - expected = fixture("with-conditional-dependency") - assert locker.written_data == expected - - installs = installer.installer.installs - assert len(installs) == 1 - - -def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency( # noqa: E501 - installer: Installer, - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, - env: NullEnv, - pool: RepositoryPool, - config: Config, -): - package.add_dependency(Factory.create_dependency("A", {"version": "^1.0"})) - - package_a = get_package("A", "1.0.0") - package_a.add_dependency( - Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]}) - ) - - package_b = get_package("B", "1.0.0") - package_b.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "optional": True}) - ) - package_b.extras = {"foo": [get_dependency("C")]} - - package_c = get_package("C", "1.0.0") - package_d = get_package("D", "1.0.0") - - repo.add_package(package_a) - repo.add_package(package_b) - repo.add_package(package_c) - repo.add_package(package_d) - - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 3 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - package.add_dependency(Factory.create_dependency("D", "^1.0")) - locker.locked(True) - locker.mock_lock_data(locker.written_data) - - installed.add_package(package_a) - installed.add_package(package_b) - installed.add_package(package_c) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - installer.update(True) - installer.whitelist(["D"]) - installer.run() - - assert len(installer.installer.installs) == 1 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - -def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency_pypi_repository( # noqa: E501 - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, - env: NullEnv, - mocker: MockerFixture, - config: Config, -): - mocker.patch("sys.platform", "darwin") - - pool = RepositoryPool() - pool.add_repository(MockRepository()) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - package.add_dependency(Factory.create_dependency("poetry", {"version": "^0.12.0"})) - - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 3 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - package.add_dependency(Factory.create_dependency("pytest", "^3.5")) - - locker.locked(True) - locker.mock_lock_data(locker.written_data) - - for pkg in installer.installer.installs: - installed.add_package(pkg) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - installer.update(True) - installer.whitelist(["pytest"]) - installer.run() - - assert len(installer.installer.installs) == 7 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - -def test_installer_required_extras_should_be_installed( - locker: Locker, - repo: Repository, - package: ProjectPackage, - installed: CustomInstalledRepository, - env: NullEnv, - config: Config, -): - pool = RepositoryPool() - pool.add_repository(MockRepository()) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - package.add_dependency( - Factory.create_dependency( - "cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]} - ) - ) - - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 2 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - locker.locked(True) - locker.mock_lock_data(locker.written_data) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 2 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - -def test_update_multiple_times_with_split_dependencies_is_idempotent( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - locker.locked(True) - locker.mock_lock_data( - { - "package": [ - { - "name": "A", - "version": "1.0", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": "*", - "checksum": [], - "dependencies": {"B": ">=1.0"}, - }, - { - "name": "B", - "version": "1.0.1", - "category": "main", - "optional": False, - "platform": "*", - "python-versions": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", - "checksum": [], - "dependencies": {}, - }, - ], - "metadata": { - "python-versions": "*", - "platform": "*", - "content-hash": "123456789", - "files": {"A": [], "B": []}, - }, - } - ) - - package.python_versions = "~2.7 || ^3.4" - package.add_dependency(Factory.create_dependency("A", "^1.0")) - - a10 = get_package("A", "1.0") - a11 = get_package("A", "1.1") - a11.add_dependency(Factory.create_dependency("B", ">=1.0.1")) - a11.add_dependency( - Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7"}) - ) - a11.add_dependency( - Factory.create_dependency("C", {"version": "^2.0", "python": "^3.4"}) - ) - b101 = get_package("B", "1.0.1") - b110 = get_package("B", "1.1.0") - repo.add_package(a10) - repo.add_package(a11) - repo.add_package(b101) - repo.add_package(b110) - repo.add_package(get_package("C", "1.0")) - repo.add_package(get_package("C", "2.0")) - expected = fixture("with-multiple-updates") - - installer.update(True) - installer.run() - - assert locker.written_data == expected - - locker.mock_lock_data(locker.written_data) - - installer.update(True) - installer.run() - - assert locker.written_data == expected - - locker.mock_lock_data(locker.written_data) - - installer.update(True) - installer.run() - - assert locker.written_data == expected - - -def test_installer_can_install_dependencies_from_forced_source( - locker: Locker, - package: ProjectPackage, - installed: CustomInstalledRepository, - env: NullEnv, - config: Config, -): - package.python_versions = "^3.7" - package.add_dependency( - Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "legacy"}) - ) - - pool = RepositoryPool() - pool.add_repository(MockLegacyRepository()) - pool.add_repository(MockRepository()) - - installer = Installer( - NullIO(), env, package, locker, pool, config, installed=installed - ) - - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 1 - assert len(installer.installer.updates) == 0 - assert len(installer.installer.removals) == 0 - - -def test_run_installs_with_url_file( - installer: Installer, locker: Locker, repo: Repository, package: ProjectPackage -): - url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" - package.add_dependency(Factory.create_dependency("demo", {"url": url})) - - repo.add_package(get_package("pendulum", "1.4.4")) - - installer.run() - - expected = fixture("with-url-dependency") - - assert locker.written_data == expected - - assert len(installer.installer.installs) == 2 - - -def test_installer_uses_prereleases_if_they_are_compatible( - installer: Installer, locker: Locker, package: ProjectPackage, repo: Repository -): - package.python_versions = "~2.7 || ^3.4" - package.add_dependency( - Factory.create_dependency( - "prerelease", {"git": "https://github.com/demo/prerelease.git"} - ) - ) - - package_b = get_package("b", "2.0.0") - package_b.add_dependency(Factory.create_dependency("prerelease", ">=0.19")) - - repo.add_package(package_b) - - installer.run() - - del installer.installer.installs[:] - locker.locked(True) - locker.mock_lock_data(locker.written_data) - - package.add_dependency(Factory.create_dependency("b", "^2.0.0")) - - installer.whitelist(["b"]) - installer.update(True) - installer.run() - - assert len(installer.installer.installs) == 2 - - -def test_installer_can_handle_old_lock_files( - locker: Locker, - package: ProjectPackage, - repo: Repository, - installed: CustomInstalledRepository, - config: Config, -): - pool = RepositoryPool() - pool.add_repository(MockRepository()) - - package.add_dependency(Factory.create_dependency("pytest", "^3.5", groups=["dev"])) - - locker.locked() - locker.mock_lock_data(fixture("old-lock")) - - installer = Installer( - NullIO(), MockEnv(), package, locker, pool, config, installed=installed - ) - - installer.run() - - assert len(installer.installer.installs) == 6 - - installer = Installer( - NullIO(), - MockEnv(version_info=(2, 7, 18)), - package, - locker, - pool, - config, - installed=installed, - ) - - installer.run() - - # funcsigs will be added - assert len(installer.installer.installs) == 7 - - installer = Installer( - NullIO(), - MockEnv(version_info=(2, 7, 18), platform="win32"), - package, - locker, - pool, - config, - installed=installed, - ) - - installer.run() - - # colorama will be added - assert len(installer.installer.installs) == 8 diff --git a/tests/installation/test_pip_installer.py b/tests/installation/test_pip_installer.py deleted file mode 100644 index d333a87b8ea..00000000000 --- a/tests/installation/test_pip_installer.py +++ /dev/null @@ -1,302 +0,0 @@ -from __future__ import annotations - -import re -import shutil - -from pathlib import Path -from typing import TYPE_CHECKING - -import pytest - -from cleo.io.null_io import NullIO -from poetry.core.packages.package import Package - -from poetry.installation.pip_installer import PipInstaller -from poetry.repositories.legacy_repository import LegacyRepository -from poetry.repositories.repository_pool import RepositoryPool -from poetry.utils.authenticator import RepositoryCertificateConfig -from poetry.utils.env import NullEnv - - -if TYPE_CHECKING: - from pytest_mock import MockerFixture - - from poetry.utils.env import VirtualEnv - from tests.conftest import Config - - -@pytest.fixture -def package_git() -> Package: - package = Package( - "demo", - "1.0.0", - source_type="git", - source_url="git@github.com:demo/demo.git", - source_reference="master", - ) - - return package - - -@pytest.fixture -def package_git_with_subdirectory() -> Package: - package = Package( - "subdirectories", - "2.0.0", - source_type="git", - source_url="https://github.com/demo/subdirectories.git", - source_reference="master", - source_subdirectory="two", - ) - - return package - - -@pytest.fixture -def pool() -> RepositoryPool: - return RepositoryPool() - - -@pytest.fixture() -def env(tmp_path: Path) -> NullEnv: - return NullEnv(path=tmp_path) - - -@pytest.fixture -def installer(pool: RepositoryPool, env: NullEnv) -> PipInstaller: - return PipInstaller(env, NullIO(), pool) - - -def test_requirement(installer: PipInstaller): - package = Package("ipython", "7.5.0") - package.files = [ - {"file": "foo-0.1.0.tar.gz", "hash": "md5:dbdc53e3918f28fa335a173432402a00"}, - { - "file": "foo.0.1.0.whl", - "hash": "e840810029224b56cd0d9e7719dc3b39cf84d577f8ac686547c8ba7a06eeab26", - }, - ] - - result = installer.requirement(package, formatted=True) - expected = ( - "ipython==7.5.0 " - "--hash md5:dbdc53e3918f28fa335a173432402a00 " - "--hash sha256:e840810029224b56cd0d9e7719dc3b39cf84d577f8ac686547c8ba7a06eeab26" - "\n" - ) - - assert result == expected - - -def test_requirement_source_type_url(env: NullEnv): - installer = PipInstaller(env, NullIO(), RepositoryPool()) - - foo = Package( - "foo", - "0.0.0", - source_type="url", - source_url="https://somewhere.com/releases/foo-1.0.0.tar.gz", - ) - - result = installer.requirement(foo, formatted=True) - expected = f"{foo.source_url}#egg={foo.name}" - - assert result == expected - - -def test_requirement_git_subdirectory( - pool: RepositoryPool, package_git_with_subdirectory: Package, env: NullEnv -) -> None: - installer = PipInstaller(env, NullIO(), pool) - result = installer.requirement(package_git_with_subdirectory) - expected = ( - "git+https://github.com/demo/subdirectories.git" - "@master#egg=subdirectories&subdirectory=two" - ) - - assert result == expected - installer.install(package_git_with_subdirectory) - assert len(env.executed) == 1 - cmd = env.executed[0] - assert Path(cmd[-1]).parts[-3:] == ("demo", "subdirectories", "two") - - -def test_requirement_git_develop_false(installer: PipInstaller, package_git: Package): - package_git.develop = False - result = installer.requirement(package_git) - expected = "git+git@github.com:demo/demo.git@master#egg=demo" - - assert result == expected - - -def test_install_with_non_pypi_default_repository( - pool: RepositoryPool, installer: PipInstaller -): - default = LegacyRepository("default", "https://default.com") - another = LegacyRepository("another", "https://another.com") - - pool.add_repository(default, default=True) - pool.add_repository(another) - - foo = Package( - "foo", - "0.0.0", - source_type="legacy", - source_reference=default.name, - source_url=default.url, - ) - bar = Package( - "bar", - "0.1.0", - source_type="legacy", - source_reference=another.name, - source_url=another.url, - ) - - installer.install(foo) - installer.install(bar) - - -@pytest.mark.parametrize( - ("key", "option"), - [ - ("client_cert", "client-cert"), - ("cert", "cert"), - ], -) -def test_install_with_certs(mocker: MockerFixture, key: str, option: str, env: NullEnv): - client_path = "path/to/client.pem" - mocker.patch( - "poetry.utils.authenticator.Authenticator.get_certs_for_url", - return_value=RepositoryCertificateConfig(**{key: Path(client_path)}), - ) - - default = LegacyRepository("default", "https://foo.bar") - pool = RepositoryPool() - pool.add_repository(default, default=True) - - installer = PipInstaller(env, NullIO(), pool) - - foo = Package( - "foo", - "0.0.0", - source_type="legacy", - source_reference=default.name, - source_url=default.url, - ) - - installer.install(foo) - - assert len(env.executed) == 1 - cmd = env.executed[0] - assert f"--{option}" in cmd - cert_index = cmd.index(f"--{option}") - # Need to do the str(Path()) bit because Windows paths get modified by Path - assert cmd[cert_index + 1] == str(Path(client_path)) - - -def test_requirement_git_develop_true(installer: PipInstaller, package_git: Package): - package_git.develop = True - result = installer.requirement(package_git) - expected = ["-e", "git+git@github.com:demo/demo.git@master#egg=demo"] - - assert result == expected - - -def test_uninstall_git_package_nspkg_pth_cleanup( - mocker: MockerFixture, tmp_venv: VirtualEnv, pool: RepositoryPool -): - # this test scenario requires a real installation using the pip installer - installer = PipInstaller(tmp_venv, NullIO(), pool) - - # use a namespace package - package = Package( - "namespace-package-one", - "1.0.0", - source_type="git", - source_url="https://github.com/demo/namespace-package-one.git", - source_reference="master", - ) - - # in order to reproduce the scenario where the git source is removed prior to proper - # clean up of nspkg.pth file, we need to make sure the fixture is copied and not - # symlinked into the git src directory - def copy_only(source: Path, dest: Path) -> None: - if dest.exists(): - dest.unlink() - - if source.is_dir(): - shutil.copytree(str(source), str(dest)) - else: - shutil.copyfile(str(source), str(dest)) - - mocker.patch("tests.helpers.copy_or_symlink", new=copy_only) - - # install package and then remove it - installer.install(package) - installer.remove(package) - - pth_file = f"{package.name}-nspkg.pth" - assert not tmp_venv.site_packages.exists(pth_file) - - # any command in the virtual environment should trigger the error message - output = tmp_venv.run("python", "-m", "site") - assert not re.match(rf"Error processing line 1 of .*{pth_file}", output) - - -def test_install_with_trusted_host(config: Config, env: NullEnv): - config.merge({"certificates": {"default": {"cert": False}}}) - - default = LegacyRepository("default", "https://foo.bar") - pool = RepositoryPool() - pool.add_repository(default, default=True) - - installer = PipInstaller(env, NullIO(), pool) - - foo = Package( - "foo", - "0.0.0", - source_type="legacy", - source_reference=default.name, - source_url=default.url, - ) - - installer.install(foo) - - assert len(env.executed) == 1 - cmd = env.executed[0] - assert "--trusted-host" in cmd - cert_index = cmd.index("--trusted-host") - assert cmd[cert_index + 1] == "foo.bar" - - -def test_install_directory_fallback_on_poetry_create_error( - mocker: MockerFixture, tmp_venv: VirtualEnv, pool: RepositoryPool -): - mock_create_poetry = mocker.patch( - "poetry.factory.Factory.create_poetry", side_effect=RuntimeError - ) - mock_sdist_builder = mocker.patch("poetry.core.masonry.builders.sdist.SdistBuilder") - mock_editable_builder = mocker.patch( - "poetry.masonry.builders.editable.EditableBuilder" - ) - mock_pip_install = mocker.patch("poetry.installation.pip_installer.pip_install") - - package = Package( - "demo", - "1.0.0", - source_type="directory", - source_url=str( - Path(__file__).parent.parent / "fixtures/inspection/demo_poetry_package" - ), - ) - - installer = PipInstaller(tmp_venv, NullIO(), pool) - installer.install_directory(package) - - assert mock_create_poetry.call_count == 1 - assert mock_sdist_builder.call_count == 0 - assert mock_editable_builder.call_count == 0 - assert mock_pip_install.call_count == 1 - assert mock_pip_install.call_args[1].get("deps") is None - assert mock_pip_install.call_args[1].get("upgrade") is True