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
This commit is contained in:
Ethan Paul 2020-09-25 00:54:45 -04:00
parent b339e3d6d9
commit db09acd8fe
No known key found for this signature in database
GPG Key ID: C5F5542B54A4D9C6

View File

@ -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)
if not venv.envconfig.skip_install:
reporter.verbosity1(
f"{_REPORTER_PREFIX} env specifies 'skip_install = false', performing installation of development package dependencies"
)
for dependency in dependencies:
reporter.verbosity0(f"{log_prefix} installing {dependency}")
installer.install(dependency)
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