Update core dep resolution functionality to use poetry compat checks

Remove custom package compatibility checks
Add checks using poetry's built in package compatibility checking using markers
Update venv integration to use poetry's venv processing tools
Remove unused constants
This commit is contained in:
2021-02-15 21:01:44 -05:00
parent d2779de848
commit 7f0aeaf539
4 changed files with 60 additions and 68 deletions

View File

@@ -2,13 +2,15 @@
# Silence this one globally to support the internal function imports for the proxied poetry module.
# See the docstring in 'tox_poetry_installer._poetry' for more context.
# pylint: disable=import-outside-toplevel
import sys
import typing
from pathlib import Path
from typing import List
from typing import Sequence
from typing import Set
from typing import Union
import tox
from poetry.core.packages import Dependency as PoetryDependency
from poetry.core.packages import Package as PoetryPackage
from tox.action import Action as ToxAction
from tox.venv import VirtualEnv as ToxVirtualEnv
@@ -56,8 +58,18 @@ def check_preconditions(venv: ToxVirtualEnv, action: ToxAction) -> "_poetry.Poet
) from None
def convert_virtualenv(venv: ToxVirtualEnv) -> "_poetry.VirtualEnv":
"""Convert a Tox venv to a Poetry venv"""
from tox_poetry_installer import _poetry
return _poetry.VirtualEnv(path=Path(venv.envconfig.envdir))
def identify_transients(
packages: PackageMap, dep_name: str, allow_missing: Sequence[str] = ()
dep: Union[PoetryDependency, str],
packages: PackageMap,
venv: "_poetry.VirtualEnv",
allow_missing: Sequence[str] = (),
) -> List[PoetryPackage]:
"""Using a pool of packages, identify all transient dependencies of a given package name
@@ -75,62 +87,45 @@ def identify_transients(
from tox_poetry_installer import _poetry
transients: List[PoetryPackage] = []
searched: Set[str] = set()
searched: Set[PoetryPackage] = set()
def _deps_of_dep(transient: PoetryDependency):
searched.add(transient.name)
def find_deps_of_deps(name: str):
searched.add(name)
if name in _poetry.Provider.UNSAFE_PACKAGES:
tox.reporter.warning(
f"{constants.REPORTER_PREFIX} Installing package '{name}' using Poetry is not supported and will be skipped"
)
if venv.is_valid_for_marker(transient.marker):
for requirement in packages[transient.name].requires:
if requirement.name not in searched:
_deps_of_dep(requirement)
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {name}: designated unsafe by Poetry"
)
return
try:
package = packages[name]
except KeyError as err:
if name in allow_missing:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {name}: package is not in lockfile but designated as allowed to be missing"
)
return
raise err
if not package.python_constraint.allows(constants.PLATFORM_VERSION):
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {package}: incompatible Python requirement '{package.python_constraint}' for current version '{constants.PLATFORM_VERSION}'"
)
elif package.platform is not None and package.platform != sys.platform:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {package}: incompatible platform requirement '{package.platform}' for current platform '{sys.platform}'"
f"{constants.REPORTER_PREFIX} Including {transient} for installation"
)
transients.append(packages[transient.name])
else:
for index, dep in enumerate(package.requires):
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Processing {package} dependency {index + 1}/{len(package.requires)}: {dep.name}"
)
if dep.name not in searched:
find_deps_of_deps(dep.name)
else:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {package}: already included for installation"
)
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Including {package} for installation"
f"{constants.REPORTER_PREFIX} Skipping {transient}: package requires {transient.marker}"
)
transients.append(package)
try:
find_deps_of_deps(packages[dep_name].name)
except KeyError:
if isinstance(dep, str):
dep = packages[dep].to_dependency()
_deps_of_dep(dep)
except KeyError as err:
dep_name = err.args[0]
if dep_name in _poetry.Provider.UNSAFE_PACKAGES:
tox.reporter.warning(
f"{constants.REPORTER_PREFIX} Installing package '{dep_name}' using Poetry is not supported and will be skipped"
)
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skipping {dep_name}: designated unsafe by Poetry"
)
return []
if dep_name in allow_missing:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skipping {dep_name}: package is allowed to be unlocked"
)
return []
if any(
@@ -148,7 +143,10 @@ def identify_transients(
def find_project_deps(
packages: PackageMap, poetry: "_poetry.Poetry", extras: Sequence[str] = ()
packages: PackageMap,
venv: "_poetry.VirtualEnv",
poetry: "_poetry.Poetry",
extras: Sequence[str] = (),
) -> List[PoetryPackage]:
"""Find the root project dependencies
@@ -180,14 +178,17 @@ def find_project_deps(
dependencies: List[PoetryPackage] = []
for dep in base_deps + extra_deps:
dependencies += identify_transients(
packages, dep.name.lower(), allow_missing=[poetry.package.name]
dep.name.lower(), packages, venv, allow_missing=[poetry.package.name]
)
return dependencies
def find_additional_deps(
packages: PackageMap, poetry: "_poetry.Poetry", dep_names: Sequence[str]
packages: PackageMap,
venv: "_poetry.VirtualEnv",
poetry: "_poetry.Poetry",
dep_names: Sequence[str],
) -> List[PoetryPackage]:
"""Find additional dependencies
@@ -201,14 +202,14 @@ def find_additional_deps(
deps: List[PoetryPackage] = []
for dep_name in dep_names:
deps += identify_transients(
packages, dep_name.lower(), allow_missing=[poetry.package.name]
dep_name.lower(), packages, venv, allow_missing=[poetry.package.name]
)
return deps
def find_dev_deps(
packages: PackageMap, poetry: "_poetry.Poetry"
packages: PackageMap, venv: "_poetry.VirtualEnv", poetry: "_poetry.Poetry"
) -> List[PoetryPackage]:
"""Find the dev dependencies
@@ -219,6 +220,7 @@ def find_dev_deps(
"""
return find_additional_deps(
packages,
venv,
poetry,
poetry.pyproject.data["tool"]["poetry"].get("dev-dependencies", {}).keys(),
)