mirror of
https://github.com/enpaul/tox-poetry-installer.git
synced 2025-10-28 07:00:43 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66f2c3c768 | |||
| fd2637113f | |||
| b10e796ca1 | |||
| 5dfbca4ff6 | |||
| db09acd8fe | |||
| b339e3d6d9 | |||
| 9db6838d94 |
@@ -255,7 +255,7 @@ usage in production systems.
|
||||
|
||||
### Path to Beta
|
||||
|
||||
- [ ] Verify that primary package dependencies (from the `.package` env) are installed
|
||||
- [X] Verify that primary package dependencies (from the `.package` env) are installed
|
||||
correctly using the Poetry backend.
|
||||
- [ ] Support the [`extras`](https://tox.readthedocs.io/en/latest/config.html#conf-extras)
|
||||
Tox configuration option
|
||||
|
||||
11
poetry.lock
generated
11
poetry.lock
generated
@@ -364,7 +364,7 @@ marker = "python_version >= \"3.6.1\" and python_version < \"4.0.0\""
|
||||
name = "identify"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
||||
version = "1.5.4"
|
||||
version = "1.5.5"
|
||||
|
||||
[package.extras]
|
||||
license = ["editdistance"]
|
||||
@@ -787,6 +787,7 @@ wcwidth = "*"
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Run a subprocess in a pseudo terminal"
|
||||
marker = "python_version >= \"3.7\" and python_version < \"4.0\" and sys_platform != \"win32\""
|
||||
name = "ptyprocess"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
@@ -1171,7 +1172,7 @@ version = "1.12.1"
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\" or python_version >= \"3.6.1\" and python_version < \"3.8\" or python_version >= \"3.5\" and python_version < \"3.8\" and (python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\" or python_version >= \"3.6.1\" and python_version < \"3.8\") or python_version >= \"3.6.1\" and python_version < \"3.7\" or python_version >= \"3.6.1\" and python_version < \"3.7\" and (python_version >= \"3.6.1\" and python_version < \"3.7\" or python_version < \"3.7\") or python_version >= \"3.6.1\" and python_version < \"3.8\" and (python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\" or python_version >= \"3.6.1\" and python_version < \"3.8\")"
|
||||
marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\" or python_version >= \"3.6.1\" and python_version < \"3.7\" or python_version >= \"3.6.1\" and python_version < \"3.8\""
|
||||
name = "zipp"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
@@ -1182,7 +1183,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
||||
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "e4a4d7c9fd7fa351a513ea4ab590e227f7c6be042a4a8a3156509f7f5df7a523"
|
||||
content-hash = "8df0839a479a0483c969368ef8f61f553773f27bdc0a569603c7141b6c360680"
|
||||
python-versions = "^3.6"
|
||||
|
||||
[metadata.files]
|
||||
@@ -1392,8 +1393,8 @@ html5lib = [
|
||||
{file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"},
|
||||
]
|
||||
identify = [
|
||||
{file = "identify-1.5.4-py2.py3-none-any.whl", hash = "sha256:d7da7de6825568daa4449858ce328ecc0e1ada2554d972a6f4f90e736aaf499a"},
|
||||
{file = "identify-1.5.4.tar.gz", hash = "sha256:e4db4796b3b0cf4f9cb921da51430abffff2d4ba7d7c521184ed5252bd90d461"},
|
||||
{file = "identify-1.5.5-py2.py3-none-any.whl", hash = "sha256:da683bfb7669fa749fc7731f378229e2dbf29a1d1337cbde04106f02236eb29d"},
|
||||
{file = "identify-1.5.5.tar.gz", hash = "sha256:7c22c384a2c9b32c5cc891d13f923f6b2653aa83e2d75d8f79be240d6c86c4f4"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "tox-poetry-installer"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
license = "MIT"
|
||||
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
||||
description = "Tox plugin to install Tox environment dependencies using the Poetry backend and lockfile"
|
||||
@@ -27,7 +27,7 @@ poetry_installer = "tox_poetry_installer"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.6"
|
||||
poetry = "^1.0.0"
|
||||
poetry = ">=1.0.0, <1.1.0"
|
||||
tox = "^2.3.0 || ^3.0.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
||||
4
tox.ini
4
tox.ini
@@ -57,6 +57,6 @@ deps =
|
||||
allowlist_externals =
|
||||
bash
|
||||
commands =
|
||||
bandit --recursive {toxinidir}/tox_poetry_installer.py
|
||||
bash -c "bandit --skip B101 {toxinidir}/tests/*.py"
|
||||
bandit --quiet {toxinidir}/tox_poetry_installer.py
|
||||
bash -c "bandit --quiet --skip B101 {toxinidir}/tests/*.py"
|
||||
bash -c "poetry export --format requirements.txt --without-hashes --dev | safety check --stdin --bare"
|
||||
|
||||
@@ -5,11 +5,11 @@ installation functionality to install dependencies from the Poetry lockfile for
|
||||
does this by using ``poetry`` to read in the lockfile, identify necessary dependencies, and then
|
||||
use Poetry's ``PipInstaller`` class to install those packages into the Tox environment.
|
||||
"""
|
||||
import logging
|
||||
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
|
||||
@@ -20,13 +20,14 @@ from poetry.packages import Package as PoetryPackage
|
||||
from poetry.puzzle.provider import Provider as PoetryProvider
|
||||
from poetry.utils.env import VirtualEnv as PoetryVirtualEnv
|
||||
from tox import hookimpl
|
||||
from tox import reporter
|
||||
from tox.action import Action as ToxAction
|
||||
from tox.venv import VirtualEnv as ToxVirtualEnv
|
||||
|
||||
|
||||
__title__ = "tox-poetry-installer"
|
||||
__summary__ = "Tox plugin to install Tox environment dependencies using the Poetry backend and lockfile"
|
||||
__version__ = "0.1.2"
|
||||
__version__ = "0.1.3"
|
||||
__url__ = "https://github.com/enpaul/tox-poetry-installer/"
|
||||
__license__ = "MIT"
|
||||
__authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
||||
@@ -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(
|
||||
@@ -72,6 +90,9 @@ def _find_locked_dependencies(
|
||||
|
||||
def find_transients(name: str) -> List[PoetryPackage]:
|
||||
if name in PoetryProvider.UNSAFE_PACKAGES:
|
||||
reporter.warning(
|
||||
f"{_REPORTER_PREFIX} installing '{name}' using Poetry is not supported; skipping"
|
||||
)
|
||||
return []
|
||||
transients = [packages[name]]
|
||||
for dep in packages[name].requires:
|
||||
@@ -109,34 +130,48 @@ def tox_testenv_install_deps(
|
||||
:param action: Tox action object
|
||||
"""
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if action.name == venv.envconfig.config.isolated_build_env:
|
||||
logger.debug(
|
||||
f"Environment {action.name} is isolated build environment; skipping Poetry-based dependency installation"
|
||||
reporter.verbosity1(
|
||||
f"{_REPORTER_PREFIX} skipping isolated build env '{action.name}'"
|
||||
)
|
||||
return None
|
||||
|
||||
poetry = _make_poetry(venv)
|
||||
poetry = PoetryFactory().create_poetry(venv.envconfig.config.toxinidir)
|
||||
|
||||
logger.debug(f"Loaded project pyproject.toml from {poetry.file}")
|
||||
reporter.verbosity1(
|
||||
f"{_REPORTER_PREFIX} loaded project pyproject.toml from {poetry.file}"
|
||||
)
|
||||
|
||||
dependencies: List[PoetryPackage] = []
|
||||
for env_dependency in venv.envconfig.deps:
|
||||
dependencies += _find_locked_dependencies(poetry, env_dependency.name)
|
||||
|
||||
logger.debug(
|
||||
f"Identified {len(dependencies)} dependencies for environment {action.name}"
|
||||
reporter.verbosity1(
|
||||
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 dev-package dependencies"
|
||||
)
|
||||
|
||||
for dependency in dependencies:
|
||||
logger.info(f"Installing environment dependency: {dependency}")
|
||||
installer.install(dependency)
|
||||
primary_dependencies = poetry.locker.locked_repository(False).packages
|
||||
reporter.verbosity1(
|
||||
f"{_REPORTER_PREFIX} identified {len(primary_dependencies)} dependencies of dev-package"
|
||||
)
|
||||
|
||||
reporter.verbosity0(
|
||||
f"{_REPORTER_PREFIX} ({venv.name}) installing {len(primary_dependencies)} dev-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 dev-package package"
|
||||
)
|
||||
|
||||
return dependencies
|
||||
|
||||
Reference in New Issue
Block a user