tox-poetry-installer/tox_poetry_installer/hooks/tox_on_install.py
Ethan Paul 198287a633
Standardize import structure
Standardize on "import module" format rather than "from module import foo" format
Remove _poetry stub module since we directly depend on the poetry package now
Fix conflicts between modules and parameters both named 'poetry'
Fixes #92
2024-08-20 14:06:51 -04:00

115 lines
4.1 KiB
Python

"""Install the dependencies for the current environment
Loads the local Poetry environment and the corresponding lockfile then pulls the dependencies
specified by the Tox environment. Finally these dependencies are installed into the Tox
environment using the Poetry ``PipInstaller`` backend.
"""
import itertools
import tox.plugin
import tox.tox_env.api
from tox_poetry_installer import exceptions
from tox_poetry_installer import logger
from tox_poetry_installer.hooks._tox_on_install_helpers import build_package_map
from tox_poetry_installer.hooks._tox_on_install_helpers import check_preconditions
from tox_poetry_installer.hooks._tox_on_install_helpers import convert_virtualenv
from tox_poetry_installer.hooks._tox_on_install_helpers import dedupe_packages
from tox_poetry_installer.hooks._tox_on_install_helpers import find_additional_deps
from tox_poetry_installer.hooks._tox_on_install_helpers import find_group_deps
from tox_poetry_installer.hooks._tox_on_install_helpers import find_project_deps
from tox_poetry_installer.hooks._tox_on_install_helpers import install_package
# pylint: disable=missing-function-docstring,unused-argument
@tox.plugin.impl
def tox_on_install(tox_env: tox.tox_env.api.ToxEnv, *args) -> None:
try:
poetry = check_preconditions(tox_env)
except exceptions.SkipEnvironment as err:
if (
isinstance(err, exceptions.PoetryNotInstalledError)
and tox_env.conf["require_poetry"]
):
logger.error(str(err))
raise err
logger.info(str(err))
return
logger.info(f"Loaded project pyproject.toml from {poetry.file}")
virtualenv = convert_virtualenv(tox_env)
try:
if not poetry.locker.is_fresh():
logger.warning(
f"The Poetry lock file is not up to date with the latest changes in {poetry.file}"
)
except FileNotFoundError as err:
logger.error(f"Could not parse lockfile: {err}")
raise exceptions.LockfileParsingError(
f"Could not parse lockfile: {err}"
) from err
try:
if tox_env.conf["require_locked_deps"] and tox_env.conf["deps"].lines():
raise exceptions.LockedDepsRequiredError(
f"Unlocked dependencies '{tox_env.conf['deps']}' specified for environment '{tox_env.name}' which requires locked dependencies"
)
packages = build_package_map(poetry)
group_deps = dedupe_packages(
list(
itertools.chain(
*[
find_group_deps(group, packages, virtualenv, poetry)
for group in tox_env.conf["poetry_dep_groups"]
]
)
)
)
logger.info(
f"Identified {len(group_deps)} group dependencies to install to env"
)
env_deps = find_additional_deps(
packages, virtualenv, poetry, tox_env.conf["locked_deps"]
)
logger.info(
f"Identified {len(env_deps)} environment dependencies to install to env"
)
# extras are not set in a testenv if skip_install=true
try:
extras = tox_env.conf["extras"]
except KeyError:
extras = []
if tox_env.conf["install_project_deps"]:
project_deps = find_project_deps(packages, virtualenv, poetry, extras)
logger.info(
f"Identified {len(project_deps)} project dependencies to install to env"
)
else:
project_deps = []
logger.info("Env does not install project package dependencies, skipping")
except exceptions.ToxPoetryInstallerException as err:
logger.error(str(err))
raise err
except Exception as err:
logger.error(f"Internal plugin error: {err}")
raise err
dependencies = dedupe_packages(group_deps + env_deps + project_deps)
logger.info(f"Installing {len(dependencies)} dependencies from Poetry lock file")
install_package(
poetry,
tox_env,
dependencies,
tox_env.options.parallel_install_threads,
)