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
|
### 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.
|
correctly using the Poetry backend.
|
||||||
- [ ] Support the [`extras`](https://tox.readthedocs.io/en/latest/config.html#conf-extras)
|
- [ ] Support the [`extras`](https://tox.readthedocs.io/en/latest/config.html#conf-extras)
|
||||||
Tox configuration option
|
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"
|
name = "identify"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
||||||
version = "1.5.4"
|
version = "1.5.5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
license = ["editdistance"]
|
license = ["editdistance"]
|
||||||
@@ -787,6 +787,7 @@ wcwidth = "*"
|
|||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Run a subprocess in a pseudo terminal"
|
description = "Run a subprocess in a pseudo terminal"
|
||||||
|
marker = "python_version >= \"3.7\" and python_version < \"4.0\" and sys_platform != \"win32\""
|
||||||
name = "ptyprocess"
|
name = "ptyprocess"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
@@ -1171,7 +1172,7 @@ version = "1.12.1"
|
|||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
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"
|
name = "zipp"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
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"]
|
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]
|
[metadata]
|
||||||
content-hash = "e4a4d7c9fd7fa351a513ea4ab590e227f7c6be042a4a8a3156509f7f5df7a523"
|
content-hash = "8df0839a479a0483c969368ef8f61f553773f27bdc0a569603c7141b6c360680"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
@@ -1392,8 +1393,8 @@ html5lib = [
|
|||||||
{file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"},
|
{file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"},
|
||||||
]
|
]
|
||||||
identify = [
|
identify = [
|
||||||
{file = "identify-1.5.4-py2.py3-none-any.whl", hash = "sha256:d7da7de6825568daa4449858ce328ecc0e1ada2554d972a6f4f90e736aaf499a"},
|
{file = "identify-1.5.5-py2.py3-none-any.whl", hash = "sha256:da683bfb7669fa749fc7731f378229e2dbf29a1d1337cbde04106f02236eb29d"},
|
||||||
{file = "identify-1.5.4.tar.gz", hash = "sha256:e4db4796b3b0cf4f9cb921da51430abffff2d4ba7d7c521184ed5252bd90d461"},
|
{file = "identify-1.5.5.tar.gz", hash = "sha256:7c22c384a2c9b32c5cc891d13f923f6b2653aa83e2d75d8f79be240d6c86c4f4"},
|
||||||
]
|
]
|
||||||
idna = [
|
idna = [
|
||||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "tox-poetry-installer"
|
name = "tox-poetry-installer"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
||||||
description = "Tox plugin to install Tox environment dependencies using the Poetry backend and lockfile"
|
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]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
poetry = "^1.0.0"
|
poetry = ">=1.0.0, <1.1.0"
|
||||||
tox = "^2.3.0 || ^3.0.0"
|
tox = "^2.3.0 || ^3.0.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
|||||||
4
tox.ini
4
tox.ini
@@ -57,6 +57,6 @@ deps =
|
|||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
bash
|
bash
|
||||||
commands =
|
commands =
|
||||||
bandit --recursive {toxinidir}/tox_poetry_installer.py
|
bandit --quiet {toxinidir}/tox_poetry_installer.py
|
||||||
bash -c "bandit --skip B101 {toxinidir}/tests/*.py"
|
bash -c "bandit --quiet --skip B101 {toxinidir}/tests/*.py"
|
||||||
bash -c "poetry export --format requirements.txt --without-hashes --dev | safety check --stdin --bare"
|
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
|
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.
|
use Poetry's ``PipInstaller`` class to install those packages into the Tox environment.
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from typing import Sequence
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from poetry.factory import Factory as PoetryFactory
|
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.puzzle.provider import Provider as PoetryProvider
|
||||||
from poetry.utils.env import VirtualEnv as PoetryVirtualEnv
|
from poetry.utils.env import VirtualEnv as PoetryVirtualEnv
|
||||||
from tox import hookimpl
|
from tox import hookimpl
|
||||||
|
from tox import reporter
|
||||||
from tox.action import Action as ToxAction
|
from tox.action import Action as ToxAction
|
||||||
from tox.venv import VirtualEnv as ToxVirtualEnv
|
from tox.venv import VirtualEnv as ToxVirtualEnv
|
||||||
|
|
||||||
|
|
||||||
__title__ = "tox-poetry-installer"
|
__title__ = "tox-poetry-installer"
|
||||||
__summary__ = "Tox plugin to install Tox environment dependencies using the Poetry backend and lockfile"
|
__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/"
|
__url__ = "https://github.com/enpaul/tox-poetry-installer/"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
__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, ...] = ("~=", "==", "!=", ">", "<")
|
_PEP508_VERSION_DELIMITERS: Tuple[str, ...] = ("~=", "==", "!=", ">", "<")
|
||||||
|
|
||||||
|
_REPORTER_PREFIX = f"[{__title__}]:"
|
||||||
|
|
||||||
|
|
||||||
class ToxPoetryInstallerException(Exception):
|
class ToxPoetryInstallerException(Exception):
|
||||||
"""Error while installing locked dependencies to the test environment"""
|
"""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"""
|
"""Cannot install a package that is not in the lockfile"""
|
||||||
|
|
||||||
|
|
||||||
def _make_poetry(venv: ToxVirtualEnv) -> Poetry:
|
def _install_to_venv(
|
||||||
"""Helper to make a poetry object from a toxenv"""
|
poetry: Poetry, venv: ToxVirtualEnv, packages: Sequence[PoetryPackage]
|
||||||
return PoetryFactory().create_poetry(venv.envconfig.config.toxinidir)
|
):
|
||||||
|
"""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(
|
def _find_locked_dependencies(
|
||||||
@@ -72,6 +90,9 @@ def _find_locked_dependencies(
|
|||||||
|
|
||||||
def find_transients(name: str) -> List[PoetryPackage]:
|
def find_transients(name: str) -> List[PoetryPackage]:
|
||||||
if name in PoetryProvider.UNSAFE_PACKAGES:
|
if name in PoetryProvider.UNSAFE_PACKAGES:
|
||||||
|
reporter.warning(
|
||||||
|
f"{_REPORTER_PREFIX} installing '{name}' using Poetry is not supported; skipping"
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
transients = [packages[name]]
|
transients = [packages[name]]
|
||||||
for dep in packages[name].requires:
|
for dep in packages[name].requires:
|
||||||
@@ -109,34 +130,48 @@ def tox_testenv_install_deps(
|
|||||||
:param action: Tox action object
|
:param action: Tox action object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
if action.name == venv.envconfig.config.isolated_build_env:
|
if action.name == venv.envconfig.config.isolated_build_env:
|
||||||
logger.debug(
|
reporter.verbosity1(
|
||||||
f"Environment {action.name} is isolated build environment; skipping Poetry-based dependency installation"
|
f"{_REPORTER_PREFIX} skipping isolated build env '{action.name}'"
|
||||||
)
|
)
|
||||||
return None
|
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] = []
|
dependencies: List[PoetryPackage] = []
|
||||||
for env_dependency in venv.envconfig.deps:
|
for env_dependency in venv.envconfig.deps:
|
||||||
dependencies += _find_locked_dependencies(poetry, env_dependency.name)
|
dependencies += _find_locked_dependencies(poetry, env_dependency.name)
|
||||||
|
|
||||||
logger.debug(
|
reporter.verbosity1(
|
||||||
f"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(
|
reporter.verbosity0(
|
||||||
env=PoetryVirtualEnv(path=Path(venv.envconfig.envdir)),
|
f"{_REPORTER_PREFIX} ({venv.name}) installing {len(dependencies)} env dependencies from lockfile"
|
||||||
io=PoetryNullIO(),
|
|
||||||
pool=poetry.pool,
|
|
||||||
)
|
)
|
||||||
|
_install_to_venv(poetry, venv, dependencies)
|
||||||
|
|
||||||
for dependency in dependencies:
|
if not venv.envconfig.skip_install:
|
||||||
logger.info(f"Installing environment dependency: {dependency}")
|
reporter.verbosity1(
|
||||||
installer.install(dependency)
|
f"{_REPORTER_PREFIX} env specifies 'skip_install = false', performing installation of dev-package dependencies"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
return dependencies
|
||||||
|
|||||||
Reference in New Issue
Block a user