8 Commits
0.2.0 ... 0.2.2

Author SHA1 Message Date
2e1d5fc922 Bump patch version 2020-09-28 23:26:19 -04:00
b7961bec58 Add support for running in a non-poetry project
Handle the error poetry raises when not in a poetry managed project
  and use that as a sign to skip further usage of the plugin in that
  environment
2020-09-28 23:24:42 -04:00
e28159060d Add badge links
Add black code format badge
2020-09-27 20:59:41 -04:00
edcef918b3 Rename 'usage' section to 'usage examples' 2020-09-27 19:41:29 -04:00
beba9416be Add note about root env setting inheritance breaking child envs 2020-09-27 19:38:42 -04:00
18a74fab63 Bump patch version 2020-09-27 15:57:00 -04:00
516515b347 Fix duplicate installation of env dependencies
Fix always logging post-sorted unlocked env dependencies
2020-09-27 15:56:29 -04:00
c9f1f41163 Fix installing package deps when skipdist is true 2020-09-27 15:56:29 -04:00
3 changed files with 49 additions and 20 deletions

View File

@@ -5,15 +5,16 @@ dependencies to be installed using [Poetry](https://python-poetry.org/) using it
⚠️ **This project is alpha software and should not be used in a production capacity** ⚠️ ⚠️ **This project is alpha software and should not be used in a production capacity** ⚠️
![image](https://img.shields.io/pypi/l/tox-poetry-installer) [![image](https://img.shields.io/pypi/l/tox-poetry-installer)](https://opensource.org/licenses/MIT)
![image](https://img.shields.io/pypi/v/tox-poetry-installer) [![image](https://img.shields.io/pypi/v/tox-poetry-installer)](https://pypi.org/project/tox-poetry-installer/)
![image](https://img.shields.io/pypi/pyversions/tox-poetry-installer) [![image](https://img.shields.io/pypi/pyversions/tox-poetry-installer)](https://www.python.org)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
**Documentation** **Documentation**
* [Installation](#installation) * [Installation](#installation)
* [Quick Start](#quick-start) * [Quick Start](#quick-start)
* [Usage](#usage) * [Usage Examples](#usage-examples)
* [Known Drawbacks and Problems](#known-drawbacks-and-problems) * [Known Drawbacks and Problems](#known-drawbacks-and-problems)
* [Why would I use this?](#why-would-i-use-this) (What problems does this solve?) * [Why would I use this?](#why-would-i-use-this) (What problems does this solve?)
* [Developing](#developing) * [Developing](#developing)
@@ -97,7 +98,7 @@ commands = ...
one Tox is testing) will always be installed from the lockfile. one Tox is testing) will always be installed from the lockfile.
## Usage ## Usage Examples
After installing the plugin to a project, your Tox automation is already benefiting from the After installing the plugin to a project, your Tox automation is already benefiting from the
lockfile: when Tox installs your project package to one of your environments, all the dependencies lockfile: when Tox installs your project package to one of your environments, all the dependencies
@@ -253,6 +254,12 @@ Tox installation backend using Pip.
* The plugin currently depends on `poetry<1.1.0`. This can be a different version than Poetry being * The plugin currently depends on `poetry<1.1.0`. This can be a different version than Poetry being
used for actual project development. (See the [road map](#roadmap)) used for actual project development. (See the [road map](#roadmap))
* Tox environments automatically inherit their settings from the main `testenv` environment. This
means that if the `require_locked_deps = true` is specified for the `testenv` environment then
all environments will also require locked dependencies. This can be overridden by explicitly
specifying `require_locked_deps = false` on child environments where unlocked dependencies are
needed.
* There are a handful of packages that cannot be installed from the lockfile, whether as specific * There are a handful of packages that cannot be installed from the lockfile, whether as specific
dependencies or as transient dependencies (dependencies of dependencies). This is due to dependencies or as transient dependencies (dependencies of dependencies). This is due to
[an ongoing discussion in the Poetry project](https://github.com/python-poetry/poetry/issues/1584); [an ongoing discussion in the Poetry project](https://github.com/python-poetry/poetry/issues/1584);

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "tox-poetry-installer" name = "tox-poetry-installer"
version = "0.2.0" version = "0.2.2"
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"

View File

@@ -10,6 +10,7 @@ from typing import Dict
from typing import List from typing import List
from typing import NamedTuple from typing import NamedTuple
from typing import Sequence from typing import Sequence
from typing import Set
from typing import Tuple from typing import Tuple
from poetry.factory import Factory as PoetryFactory from poetry.factory import Factory as PoetryFactory
@@ -29,7 +30,7 @@ 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.2.0" __version__ = "0.2.2"
__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>"]
@@ -139,7 +140,7 @@ def _install_to_venv(
installer.install(dependency) installer.install(dependency)
def _find_transients(poetry: Poetry, dependency_name: str) -> List[PoetryPackage]: def _find_transients(poetry: Poetry, dependency_name: str) -> Set[PoetryPackage]:
"""Using a poetry object identify all dependencies of a specific dependency """Using a poetry object identify all dependencies of a specific dependency
:param poetry: Populated poetry object which can be used to build a populated locked :param poetry: Populated poetry object which can be used to build a populated locked
@@ -170,7 +171,7 @@ def _find_transients(poetry: Poetry, dependency_name: str) -> List[PoetryPackage
transients += find_deps_of_deps(dep.name) transients += find_deps_of_deps(dep.name)
return transients return transients
return find_deps_of_deps(top_level.name) return set(find_deps_of_deps(top_level.name))
except KeyError: except KeyError:
if any( if any(
@@ -187,17 +188,12 @@ def _find_transients(poetry: Poetry, dependency_name: str) -> List[PoetryPackage
def _install_env_dependencies(venv: ToxVirtualEnv, poetry: Poetry): def _install_env_dependencies(venv: ToxVirtualEnv, poetry: Poetry):
env_deps = _sort_env_deps(venv) env_deps = _sort_env_deps(venv)
reporter.verbosity1(
f"{_REPORTER_PREFIX} updating env config with {len(env_deps.unlocked_deps)} unlocked env dependencies for installation using the default backend"
)
venv.envconfig.deps = env_deps.unlocked_deps
dependencies: List[PoetryPackage] = [] dependencies: List[PoetryPackage] = []
for dep in env_deps.locked_deps: for dep in env_deps.locked_deps:
try: try:
dependencies += _find_transients(poetry, dep.name) dependencies += _find_transients(poetry, dep.name)
except ToxPoetryInstallerException as err: except ToxPoetryInstallerException as err:
venv.status = "install-locked-deps-failed" venv.status = "lockfile installation failed"
reporter.error(f"{_REPORTER_PREFIX} {err}") reporter.error(f"{_REPORTER_PREFIX} {err}")
raise err raise err
@@ -205,6 +201,11 @@ def _install_env_dependencies(venv: ToxVirtualEnv, poetry: Poetry):
f"{_REPORTER_PREFIX} identified {len(dependencies)} actual dependencies from {len(venv.envconfig.deps)} specified env dependencies" f"{_REPORTER_PREFIX} identified {len(dependencies)} actual dependencies from {len(venv.envconfig.deps)} specified env dependencies"
) )
reporter.verbosity1(
f"{_REPORTER_PREFIX} updating env config with {len(env_deps.unlocked_deps)} unlocked env dependencies for installation using the default backend"
)
venv.envconfig.deps = env_deps.unlocked_deps
reporter.verbosity0( reporter.verbosity0(
f"{_REPORTER_PREFIX} ({venv.name}) installing {len(dependencies)} env dependencies from lockfile" f"{_REPORTER_PREFIX} ({venv.name}) installing {len(dependencies)} env dependencies from lockfile"
) )
@@ -265,7 +266,23 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction):
) )
return return
poetry = PoetryFactory().create_poetry(venv.envconfig.config.toxinidir) try:
poetry = PoetryFactory().create_poetry(venv.envconfig.config.toxinidir)
except RuntimeError as err:
# Support running the plugin when the current tox project does not use Poetry for its
# environment/dependency management.
#
# ``RuntimeError`` is dangerous to blindly catch because it can be (and in Poetry's case,
# is) raised in many different places for different purposes. This check of the error
# content, while crude and potentially fragile, will hopefully prevent ``RuntimeError``s
# not caused by this specific condition to be re-raised as genuine errors. This may need
# tuning in the future.
if "[tool.poetry] section not found" in str(err):
reporter.verbosity1(
f"{_REPORTER_PREFIX} project does not use Poetry for env management, skipping installation of locked dependencies"
)
return
raise err
reporter.verbosity1( reporter.verbosity1(
f"{_REPORTER_PREFIX} loaded project pyproject.toml from {poetry.file}" f"{_REPORTER_PREFIX} loaded project pyproject.toml from {poetry.file}"
@@ -276,9 +293,14 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction):
# Handle the installation of the package dependencies from the lockfile if the package is # Handle the installation of the package dependencies from the lockfile if the package is
# being installed to this venv; otherwise skip installing the package dependencies # being installed to this venv; otherwise skip installing the package dependencies
if not venv.envconfig.skip_install: if not venv.envconfig.skip_install and not venv.envconfig.config.skipsdist:
_install_package_dependencies(venv, poetry) _install_package_dependencies(venv, poetry)
else: else:
reporter.verbosity1( if venv.envconfig.skip_install:
f"{_REPORTER_PREFIX} env specifies 'skip_install = true', skipping installation of project package" reporter.verbosity1(
) f"{_REPORTER_PREFIX} env specifies 'skip_install = true', skipping installation of project package"
)
elif venv.envconfig.config.skipsdist:
reporter.verbosity1(
f"{_REPORTER_PREFIX} config specifies 'skipsdist = true', skipping installation of project package"
)