From db09acd8fe017d95c1a1b0489854b0385d23e472 Mon Sep 17 00:00:00 2001 From: Ethan Paul <24588726+enpaul@users.noreply.github.com> Date: Fri, 25 Sep 2020 00:54:45 -0400 Subject: [PATCH] Fix install of dev package dependencies from lockfile Override default pip behavior by preemptively installing dev package dependencies Keep support for tox default skip_install config flag --- tox_poetry_installer.py | 64 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/tox_poetry_installer.py b/tox_poetry_installer.py index a51ef24..4a8613c 100644 --- a/tox_poetry_installer.py +++ b/tox_poetry_installer.py @@ -9,6 +9,7 @@ from pathlib import Path from typing import Dict from typing import List from typing import Optional +from typing import Sequence from typing import Tuple from poetry.factory import Factory as PoetryFactory @@ -34,6 +35,8 @@ __authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] _PEP508_VERSION_DELIMITERS: Tuple[str, ...] = ("~=", "==", "!=", ">", "<") +_REPORTER_PREFIX = f"[{__title__}]:" + class ToxPoetryInstallerException(Exception): """Error while installing locked dependencies to the test environment""" @@ -43,9 +46,24 @@ class NoLockedDependencyError(ToxPoetryInstallerException): """Cannot install a package that is not in the lockfile""" -def _make_poetry(venv: ToxVirtualEnv) -> Poetry: - """Helper to make a poetry object from a toxenv""" - return PoetryFactory().create_poetry(venv.envconfig.config.toxinidir) +def _install_to_venv( + poetry: Poetry, venv: ToxVirtualEnv, packages: Sequence[PoetryPackage] +): + """Install a bunch of packages to a virtualenv + + :param poetry: Poetry object the packages were sourced from + :param venv: Tox virtual environment to install the packages to + :param packages: List of packages to install to the virtual environment + """ + installer = PoetryPipInstaller( + env=PoetryVirtualEnv(path=Path(venv.envconfig.envdir)), + io=PoetryNullIO(), + pool=poetry.pool, + ) + + for dependency in packages: + reporter.verbosity1(f"{_REPORTER_PREFIX} installing {dependency}") + installer.install(dependency) def _find_locked_dependencies( @@ -73,7 +91,7 @@ def _find_locked_dependencies( def find_transients(name: str) -> List[PoetryPackage]: if name in PoetryProvider.UNSAFE_PACKAGES: reporter.warning( - f"Installing '{name}' using Poetry is not supported; skipping" + f"{_REPORTER_PREFIX} installing '{name}' using Poetry is not supported; skipping" ) return [] transients = [packages[name]] @@ -112,18 +130,16 @@ def tox_testenv_install_deps( :param action: Tox action object """ - log_prefix = f"[{__title__}] {venv.name} installdeps:" - if action.name == venv.envconfig.config.isolated_build_env: reporter.verbosity1( - f"{log_prefix} skipping isolated build environment '{action.name}'" + f"{_REPORTER_PREFIX} skipping isolated build environment '{action.name}'" ) return None - poetry = _make_poetry(venv) + poetry = PoetryFactory().create_poetry(venv.envconfig.config.toxinidir) reporter.verbosity1( - f"{log_prefix} loaded project pyproject.toml from {poetry.file}" + f"{_REPORTER_PREFIX} loaded project pyproject.toml from {poetry.file}" ) dependencies: List[PoetryPackage] = [] @@ -131,17 +147,31 @@ def tox_testenv_install_deps( dependencies += _find_locked_dependencies(poetry, env_dependency.name) reporter.verbosity1( - f"{log_prefix} identified {len(dependencies)} dependencies for environment {action.name}" + f"{_REPORTER_PREFIX} identified {len(dependencies)} actual dependencies from {len(venv.envconfig.deps)} specified env dependencies" ) - installer = PoetryPipInstaller( - env=PoetryVirtualEnv(path=Path(venv.envconfig.envdir)), - io=PoetryNullIO(), - pool=poetry.pool, + reporter.verbosity0( + f"{_REPORTER_PREFIX} ({venv.name}) installing {len(dependencies)} env dependencies from lockfile" ) + _install_to_venv(poetry, venv, dependencies) - for dependency in dependencies: - reporter.verbosity0(f"{log_prefix} installing {dependency}") - installer.install(dependency) + if not venv.envconfig.skip_install: + reporter.verbosity1( + f"{_REPORTER_PREFIX} env specifies 'skip_install = false', performing installation of development package dependencies" + ) + + primary_dependencies = poetry.locker.locked_repository(False).packages + reporter.verbosity1( + f"{_REPORTER_PREFIX} identified {len(primary_dependencies)} dependencies of development package" + ) + + reporter.verbosity0( + f"{_REPORTER_PREFIX} ({venv.name}) installing {len(primary_dependencies)} development package dependencies from lockfile" + ) + _install_to_venv(poetry, venv, primary_dependencies) + else: + reporter.verbosity1( + f"{_REPORTER_PREFIX} env specifies 'skip_install = true', skipping installation of top-level package" + ) return dependencies