mirror of
https://github.com/enpaul/tox-poetry-installer.git
synced 2025-01-15 08:43:29 +00:00
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:
parent
d2779de848
commit
7f0aeaf539
@ -5,11 +5,8 @@ in this module.
|
||||
|
||||
All constants should be type hinted.
|
||||
"""
|
||||
import sys
|
||||
from typing import Tuple
|
||||
|
||||
from poetry.core.semver.version import Version
|
||||
|
||||
from tox_poetry_installer import __about__
|
||||
|
||||
|
||||
@ -20,12 +17,3 @@ PEP508_VERSION_DELIMITERS: Tuple[str, ...] = ("~=", "==", "!=", ">", "<")
|
||||
# Prefix all reporter messages should include to indicate that they came from this module in the
|
||||
# console output.
|
||||
REPORTER_PREFIX: str = f"{__about__.__title__}:"
|
||||
|
||||
|
||||
# Semver compatible version of the current python platform version. Used for checking
|
||||
# whether a package is compatible with the current python system version
|
||||
PLATFORM_VERSION: Version = Version(
|
||||
major=sys.version_info.major,
|
||||
minor=sys.version_info.minor,
|
||||
patch=sys.version_info.micro,
|
||||
)
|
||||
|
@ -84,6 +84,8 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional
|
||||
f"{constants.REPORTER_PREFIX} Loaded project pyproject.toml from {poetry.file}"
|
||||
)
|
||||
|
||||
virtualenv = utilities.convert_virtualenv(venv)
|
||||
|
||||
if not poetry.locker.is_fresh():
|
||||
tox.reporter.warning(
|
||||
f"The Poetry lock file is not up to date with the latest changes in {poetry.file}"
|
||||
@ -101,7 +103,7 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional
|
||||
}
|
||||
|
||||
if venv.envconfig.install_dev_deps:
|
||||
dev_deps = utilities.find_dev_deps(packages, poetry)
|
||||
dev_deps = utilities.find_dev_deps(packages, virtualenv, poetry)
|
||||
tox.reporter.verbosity1(
|
||||
f"{constants.REPORTER_PREFIX} Identified {len(dev_deps)} development dependencies to install to env"
|
||||
)
|
||||
@ -112,7 +114,7 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional
|
||||
)
|
||||
|
||||
env_deps = utilities.find_additional_deps(
|
||||
packages, poetry, venv.envconfig.locked_deps
|
||||
packages, virtualenv, poetry, venv.envconfig.locked_deps
|
||||
)
|
||||
|
||||
tox.reporter.verbosity1(
|
||||
@ -121,7 +123,7 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional
|
||||
|
||||
if not venv.envconfig.skip_install and not venv.envconfig.config.skipsdist:
|
||||
project_deps = utilities.find_project_deps(
|
||||
packages, poetry, venv.envconfig.extras
|
||||
packages, virtualenv, poetry, venv.envconfig.extras
|
||||
)
|
||||
tox.reporter.verbosity1(
|
||||
f"{constants.REPORTER_PREFIX} Identified {len(project_deps)} project dependencies to install to env"
|
||||
|
@ -3,7 +3,6 @@
|
||||
# See the docstring in 'tox_poetry_installer._poetry' for more context.
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
from typing import Set
|
||||
|
||||
@ -12,6 +11,7 @@ from poetry.core.packages import Package as PoetryPackage
|
||||
from tox.venv import VirtualEnv as ToxVirtualEnv
|
||||
|
||||
from tox_poetry_installer import constants
|
||||
from tox_poetry_installer import utilities
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from tox_poetry_installer import _poetry
|
||||
@ -33,7 +33,7 @@ def install(
|
||||
)
|
||||
|
||||
pip = _poetry.PipInstaller(
|
||||
env=_poetry.VirtualEnv(path=Path(venv.envconfig.envdir)),
|
||||
env=utilities.convert_virtualenv(venv),
|
||||
io=_poetry.NullIO(),
|
||||
pool=poetry.pool,
|
||||
)
|
||||
@ -49,5 +49,5 @@ def install(
|
||||
installed.add(dependency)
|
||||
else:
|
||||
tox.reporter.verbosity2(
|
||||
f"{constants.REPORTER_PREFIX} Already installed {dependency}, skipping"
|
||||
f"{constants.REPORTER_PREFIX} Skipping {dependency}, already installed"
|
||||
)
|
||||
|
@ -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(),
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user