12 Commits
0.6.2 ... 0.6.3

Author SHA1 Message Date
ba5cd94b5e Merge pull request #42 from enpaul/enp/bugs
Fix non-deterministic package installation order
2021-02-10 00:19:12 -05:00
a91364efd6 Bump patch version 2021-02-10 00:07:34 -05:00
e894a25d18 Update logging messages to improve UX and output consistency 2021-02-10 00:07:34 -05:00
08a6962d3f General refactoring
Fix some pseudo-hungarian type notation
Fix out of date docstrings
Fix arbitrary argument ordering in function signatures
Remove interchangable usage of dep/dependency variable naming
Remove interchangable usage of packages/package_map for same data
2021-02-10 00:07:34 -05:00
b8ea98b3ad Move install function to dedicated submodule
Fix duplicate package installs caused by using list for ordering
2021-02-10 00:07:34 -05:00
ea8bc3887e Fix non-deterministic dependency order resolution
Unordered sets strike again. By casting a list of packages to a set
to ensure uniqueness the installation of the packages becomes non-deterministic.
This is not great, but it trivially breaks installing packages that require
their dependencies for installation.

Fixes #41
2021-02-10 00:07:33 -05:00
52c08e9dc5 Update import pattern to use tox module namespacing where possible 2021-02-10 00:07:33 -05:00
ee5df2f17a Update pre-commit config to follow best practices
https://github.com/pre-commit/pre-commit/issues/1790
2021-02-09 20:20:47 -05:00
46b8fcc2a4 Update tox dependency spec from ^3.0 to ^3.8 for compatibility 2021-01-27 21:29:14 -05:00
469ce4c905 Update feature roadmap with latest changes 2021-01-27 18:05:58 -05:00
5b5896191f Clarify local dev requirements 2021-01-27 18:04:02 -05:00
cc54e6243a Add dev makefile target for setting up the local dev env 2021-01-27 18:00:24 -05:00
10 changed files with 392 additions and 294 deletions

View File

@@ -13,36 +13,57 @@
# by the Poetry-managed dependency.
#
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
- repo: local
hooks:
- id: end-of-file-fixer
name: end-of-file-fixer
entry: end-of-file-fixer
language: system
types:
- text
- id: fix-encoding-pragma
name: fix-encoding-pragma
entry: fix-encoding-pragma
language: system
args:
- "--remove"
types:
- python
- id: trailing-whitespace-fixer
name: trailing-whitespace-fixer
entry: trailing-whitespace-fixer
language: system
- id: trailing-whitespace
language: system
types:
- text
- id: check-merge-conflict
name: check-merge-conflict
entry: check-merge-conflict
language: system
types:
- text
- repo: https://github.com/psf/black
rev: 20.8b1
hooks:
- id: black
language: system
- repo: https://github.com/asottile/blacken-docs
rev: v1.8.0
hooks:
- id: blacken-docs
language: system
- repo: https://github.com/asottile/reorder_python_imports
rev: v2.3.6
hooks:
- id: reorder-python-imports
name: reorder-python-imports
entry: reorder-python-imports
language: system
args:
- "--unclassifiable-application-module=tox_poetry_installer"
types:
- python
- id: black
name: black
entry: black
language: system
types:
- python
- id: blacken-docs
name: blacken-docs
entry: blacken-docs
language: system
types:
- text

View File

@@ -32,5 +32,9 @@ source: ## Build Python source distribution package
test: ## Run the project testsuite(s)
poetry run tox --recreate
publish: wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set)
dev: ## Create the local dev environment
poetry install -E poetry
poetry run pre-commit install
publish: test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set)
@poetry publish --username __token__ --password $(PYPI_API_KEY)

View File

@@ -479,8 +479,10 @@ the [`--require-poetry`](#--require-poetry) option.
## Developing
This project requires Poetry version 1.0+ on the development workstation, see
the [installation instructions here](https://python-poetry.org/docs/#installation).
Local development requirements:
* Python version 3.6+ ([install](https://www.python.org/downloads/))
* Poetry version 1.0+ ([install](https://python-poetry.org/docs/#installation))
* GNU Make (optional, required to use the makefile)
Local environment setup instructions:
@@ -491,15 +493,16 @@ git clone https://github.com/enpaul/tox-poetry-installer.git
# ...over SSH
git clone git@github.com:enpaul/tox-poetry-installer.git
# Create a the local project virtual environment and install dependencies
cd tox-poetry-installer
poetry install -E poetry
cd tox-poetry-installer/
# Install pre-commit hooks
poetry run pre-commit install
# Create and configure the local development environment
make dev
# Run tests and static analysis
poetry run tox
# Run tests and CI locally
make test
# Check additional make targets
make help
```
**NOTE:** Because the pre-commit hooks require dependencies in the Poetry environment it
@@ -547,14 +550,14 @@ production environments on a provisional basis only.
- [X] Add per-environment Tox configuration option to fall back to default installation
backend.
- [ ] ~Add warnings when an unsupported Tox configuration option is detected while using the
Poetry backend. ([#5](https://github.com/enpaul/tox-poetry-installer/issues/5))~
Poetry backend.~ ([#5](https://github.com/enpaul/tox-poetry-installer/issues/5))
- [X] Add trivial tests to ensure the project metadata is consistent between the pyproject.toml
and the module constants.
- [X] Update to use [poetry-core](https://github.com/python-poetry/poetry-core) and
improve robustness of the Tox and Poetry module imports
to avoid potentially breaking API changes in upstream packages. ([#2](https://github.com/enpaul/tox-poetry-installer/issues/2))
- [ ] ~Find and implement a way to mitigate the [UNSAFE_DEPENDENCIES issue](https://github.com/python-poetry/poetry/issues/1584) in Poetry.
([#6](https://github.com/enpaul/tox-poetry-installer/issues/6))~
- [ ] ~Find and implement a way to mitigate the [UNSAFE_DEPENDENCIES issue](https://github.com/python-poetry/poetry/issues/1584) in Poetry.~
([#6](https://github.com/enpaul/tox-poetry-installer/issues/6))
- [X] Fix logging to make proper use of Tox's logging reporter infrastructure ([#3](https://github.com/enpaul/tox-poetry-installer/issues/3))
- [X] Add configuration option for installing all dev-dependencies to a testenv ([#14](https://github.com/enpaul/tox-poetry-installer/issues/14))
@@ -562,9 +565,10 @@ production environments on a provisional basis only.
Everything in Beta plus...
- [ ] Fully replace dependency on `poetry` with dependency on `poetry-core` ([#2](https://github.com/enpaul/tox-poetry-installer/issues/2))
- [ ] Add comprehensive unit tests
- [ ] Add tests for each feature version of Tox between 3.0 and 3.20
- [ ] Add tests for Python-3.6, 3.7, 3.8, and 3.9
- [X] Add tests for Python-3.6, 3.7, 3.8, and 3.9
- [X] Add Github Actions based CI
- [ ] Add CI for CPython, PyPy, and Conda
- [ ] Add CI for Linux and Windows

177
poetry.lock generated
View File

@@ -71,16 +71,16 @@ python-versions = "*"
[[package]]
name = "bandit"
version = "1.6.2"
version = "1.7.0"
description = "Security oriented static analyser for python code."
category = "dev"
optional = false
python-versions = "*"
python-versions = ">=3.5"
[package.dependencies]
colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
GitPython = ">=1.0.1"
PyYAML = ">=3.13"
PyYAML = ">=5.3.1"
six = ">=1.10.0"
stevedore = ">=1.20.0"
@@ -158,7 +158,7 @@ msgpack = ["msgpack-python (>=0.5,<0.6)"]
[[package]]
name = "certifi"
version = "2020.11.8"
version = "2020.12.5"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
@@ -185,11 +185,11 @@ python-versions = ">=3.6.1"
[[package]]
name = "chardet"
version = "3.0.4"
version = "4.0.0"
description = "Universal encoding detector for Python 2 and 3"
category = "main"
optional = false
python-versions = "*"
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "cleo"
@@ -252,14 +252,14 @@ python-versions = ">=3.6,<4.0"
[[package]]
name = "cryptography"
version = "3.2.1"
version = "3.3.1"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "main"
optional = true
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*"
[package.dependencies]
cffi = ">=1.8,<1.11.3 || >1.11.3"
cffi = ">=1.12"
six = ">=1.4.1"
[package.extras]
@@ -535,7 +535,7 @@ python-versions = "*"
[[package]]
name = "msgpack"
version = "1.0.0"
version = "1.0.1"
description = "MessagePack (de)serializer."
category = "main"
optional = true
@@ -575,7 +575,7 @@ python-versions = "*"
[[package]]
name = "packaging"
version = "20.7"
version = "20.8"
description = "Core utilities for Python packages"
category = "main"
optional = false
@@ -703,7 +703,7 @@ importlib-metadata = {version = ">=1.7.0,<2.0.0", markers = "python_version >= \
[[package]]
name = "pre-commit"
version = "2.9.2"
version = "2.9.3"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev"
optional = false
@@ -721,7 +721,7 @@ virtualenv = ">=20.0.8"
[[package]]
name = "pre-commit-hooks"
version = "3.3.0"
version = "3.4.0"
description = "Some out-of-the-box hooks for pre-commit."
category = "dev"
optional = false
@@ -768,7 +768,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pygments"
version = "2.7.2"
version = "2.7.3"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
@@ -807,25 +807,24 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "pytest"
version = "6.1.2"
version = "6.2.1"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.5"
python-versions = ">=3.6"
[package.dependencies]
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
attrs = ">=17.4.0"
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<1.0"
pluggy = ">=0.12,<1.0.0a1"
py = ">=1.8.2"
toml = "*"
[package.extras]
checkqa_mypy = ["mypy (==0.780)"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
@@ -880,7 +879,7 @@ python-versions = ">=3.6.1"
[[package]]
name = "requests"
version = "2.25.0"
version = "2.25.1"
description = "Python HTTP for Humans."
category = "main"
optional = false
@@ -888,7 +887,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[package.dependencies]
certifi = ">=2017.4.17"
chardet = ">=3.0.2,<4"
chardet = ">=3.0.2,<5"
idna = ">=2.5,<3"
urllib3 = ">=1.21.1,<1.27"
@@ -1076,7 +1075,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "virtualenv"
version = "20.2.1"
version = "20.2.2"
description = "Virtual Python Environment builder"
category = "main"
optional = false
@@ -1136,7 +1135,7 @@ poetry = ["poetry"]
[metadata]
lock-version = "1.1"
python-versions = "^3.6.1"
content-hash = "a5ba6181fc3728d85a60b2e089b9afe2d5bf75f361526e6972d48a42e5075c32"
content-hash = "6c467c16dc076332b719698f793626577eb839f286fabcfa8df8c59b5ff891ca"
[metadata.files]
appdirs = [
@@ -1168,8 +1167,8 @@ backcall = [
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
]
bandit = [
{file = "bandit-1.6.2-py2.py3-none-any.whl", hash = "sha256:336620e220cf2d3115877685e264477ff9d9abaeb0afe3dc7264f55fa17a3952"},
{file = "bandit-1.6.2.tar.gz", hash = "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"},
{file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"},
{file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"},
]
black = [
{file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
@@ -1191,8 +1190,8 @@ cachy = [
{file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"},
]
certifi = [
{file = "certifi-2020.11.8-py2.py3-none-any.whl", hash = "sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd"},
{file = "certifi-2020.11.8.tar.gz", hash = "sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4"},
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
{file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
]
cffi = [
{file = "cffi-1.14.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775"},
@@ -1237,8 +1236,8 @@ cfgv = [
{file = "cfgv-3.2.0.tar.gz", hash = "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"},
]
chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
]
cleo = [
{file = "cleo-0.8.1-py2.py3-none-any.whl", hash = "sha256:141cda6dc94a92343be626bb87a0b6c86ae291dfc732a57bf04310d4b4201753"},
@@ -1297,28 +1296,20 @@ crashtest = [
{file = "crashtest-0.3.1.tar.gz", hash = "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd"},
]
cryptography = [
{file = "cryptography-3.2.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:6dc59630ecce8c1f558277ceb212c751d6730bd12c80ea96b4ac65637c4f55e7"},
{file = "cryptography-3.2.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:75e8e6684cf0034f6bf2a97095cb95f81537b12b36a8fedf06e73050bb171c2d"},
{file = "cryptography-3.2.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4e7268a0ca14536fecfdf2b00297d4e407da904718658c1ff1961c713f90fd33"},
{file = "cryptography-3.2.1-cp27-cp27m-win32.whl", hash = "sha256:7117319b44ed1842c617d0a452383a5a052ec6aa726dfbaffa8b94c910444297"},
{file = "cryptography-3.2.1-cp27-cp27m-win_amd64.whl", hash = "sha256:a733671100cd26d816eed39507e585c156e4498293a907029969234e5e634bc4"},
{file = "cryptography-3.2.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:a75f306a16d9f9afebfbedc41c8c2351d8e61e818ba6b4c40815e2b5740bb6b8"},
{file = "cryptography-3.2.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5849d59358547bf789ee7e0d7a9036b2d29e9a4ddf1ce5e06bb45634f995c53e"},
{file = "cryptography-3.2.1-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:bd717aa029217b8ef94a7d21632a3bb5a4e7218a4513d2521c2a2fd63011e98b"},
{file = "cryptography-3.2.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:efe15aca4f64f3a7ea0c09c87826490e50ed166ce67368a68f315ea0807a20df"},
{file = "cryptography-3.2.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:32434673d8505b42c0de4de86da8c1620651abd24afe91ae0335597683ed1b77"},
{file = "cryptography-3.2.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:7b8d9d8d3a9bd240f453342981f765346c87ade811519f98664519696f8e6ab7"},
{file = "cryptography-3.2.1-cp35-cp35m-win32.whl", hash = "sha256:d3545829ab42a66b84a9aaabf216a4dce7f16dbc76eb69be5c302ed6b8f4a29b"},
{file = "cryptography-3.2.1-cp35-cp35m-win_amd64.whl", hash = "sha256:a4e27ed0b2504195f855b52052eadcc9795c59909c9d84314c5408687f933fc7"},
{file = "cryptography-3.2.1-cp36-abi3-win32.whl", hash = "sha256:13b88a0bd044b4eae1ef40e265d006e34dbcde0c2f1e15eb9896501b2d8f6c6f"},
{file = "cryptography-3.2.1-cp36-abi3-win_amd64.whl", hash = "sha256:07ca431b788249af92764e3be9a488aa1d39a0bc3be313d826bbec690417e538"},
{file = "cryptography-3.2.1-cp36-cp36m-win32.whl", hash = "sha256:a035a10686532b0587d58a606004aa20ad895c60c4d029afa245802347fab57b"},
{file = "cryptography-3.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:d26a2557d8f9122f9bf445fc7034242f4375bd4e95ecda007667540270965b13"},
{file = "cryptography-3.2.1-cp37-cp37m-win32.whl", hash = "sha256:545a8550782dda68f8cdc75a6e3bf252017aa8f75f19f5a9ca940772fc0cb56e"},
{file = "cryptography-3.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:55d0b896631412b6f0c7de56e12eb3e261ac347fbaa5d5e705291a9016e5f8cb"},
{file = "cryptography-3.2.1-cp38-cp38-win32.whl", hash = "sha256:3cd75a683b15576cfc822c7c5742b3276e50b21a06672dc3a800a2d5da4ecd1b"},
{file = "cryptography-3.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:d25cecbac20713a7c3bc544372d42d8eafa89799f492a43b79e1dfd650484851"},
{file = "cryptography-3.2.1.tar.gz", hash = "sha256:d3d5e10be0cf2a12214ddee45c6bd203dab435e3d83b4560c03066eda600bfe3"},
{file = "cryptography-3.3.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030"},
{file = "cryptography-3.3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0"},
{file = "cryptography-3.3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812"},
{file = "cryptography-3.3.1-cp27-cp27m-win32.whl", hash = "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e"},
{file = "cryptography-3.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901"},
{file = "cryptography-3.3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d"},
{file = "cryptography-3.3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5"},
{file = "cryptography-3.3.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302"},
{file = "cryptography-3.3.1-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244"},
{file = "cryptography-3.3.1-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c"},
{file = "cryptography-3.3.1-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c"},
{file = "cryptography-3.3.1-cp36-abi3-win32.whl", hash = "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a"},
{file = "cryptography-3.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7"},
{file = "cryptography-3.3.1.tar.gz", hash = "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6"},
]
dataclasses = [
{file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"},
@@ -1428,24 +1419,44 @@ mccabe = [
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
]
msgpack = [
{file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"},
{file = "msgpack-1.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aa5c057eab4f40ec47ea6f5a9825846be2ff6bf34102c560bad5cad5a677c5be"},
{file = "msgpack-1.0.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:4233b7f86c1208190c78a525cd3828ca1623359ef48f78a6fea4b91bb995775a"},
{file = "msgpack-1.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b3758dfd3423e358bbb18a7cccd1c74228dffa7a697e5be6cb9535de625c0dbf"},
{file = "msgpack-1.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25b3bc3190f3d9d965b818123b7752c5dfb953f0d774b454fd206c18fe384fb8"},
{file = "msgpack-1.0.0-cp36-cp36m-win32.whl", hash = "sha256:e7bbdd8e2b277b77782f3ce34734b0dfde6cbe94ddb74de8d733d603c7f9e2b1"},
{file = "msgpack-1.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5dba6d074fac9b24f29aaf1d2d032306c27f04187651511257e7831733293ec2"},
{file = "msgpack-1.0.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:908944e3f038bca67fcfedb7845c4a257c7749bf9818632586b53bcf06ba4b97"},
{file = "msgpack-1.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:db685187a415f51d6b937257474ca72199f393dad89534ebbdd7d7a3b000080e"},
{file = "msgpack-1.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea41c9219c597f1d2bf6b374d951d310d58684b5de9dc4bd2976db9e1e22c140"},
{file = "msgpack-1.0.0-cp37-cp37m-win32.whl", hash = "sha256:e35b051077fc2f3ce12e7c6a34cf309680c63a842db3a0616ea6ed25ad20d272"},
{file = "msgpack-1.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5bea44181fc8e18eed1d0cd76e355073f00ce232ff9653a0ae88cb7d9e643322"},
{file = "msgpack-1.0.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c901e8058dd6653307906c5f157f26ed09eb94a850dddd989621098d347926ab"},
{file = "msgpack-1.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:271b489499a43af001a2e42f42d876bb98ccaa7e20512ff37ca78c8e12e68f84"},
{file = "msgpack-1.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7a22c965588baeb07242cb561b63f309db27a07382825fc98aecaf0827c1538e"},
{file = "msgpack-1.0.0-cp38-cp38-win32.whl", hash = "sha256:002a0d813e1f7b60da599bdf969e632074f9eec1b96cbed8fb0973a63160a408"},
{file = "msgpack-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:39c54fdebf5fa4dda733369012c59e7d085ebdfe35b6cf648f09d16708f1be5d"},
{file = "msgpack-1.0.0.tar.gz", hash = "sha256:9534d5cc480d4aff720233411a1f765be90885750b07df772380b34c10ecb5c0"},
{file = "msgpack-1.0.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4bea1938e484c9caca9585105f447d6807c496c153b7244fa726b3cc4a68ec9e"},
{file = "msgpack-1.0.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:2966b155356fd231fa441131d7301e1596ee38974ad56dc57fd752fdbe2bb63f"},
{file = "msgpack-1.0.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:c82fc6cdba5737eb6ed0c926a30a5d56e7b050297375a16d6c5ad89b576fd979"},
{file = "msgpack-1.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:e157edf4213dacafb0f862e0b7a3a18448250cec91aa1334f432f49028acc650"},
{file = "msgpack-1.0.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:35ff1ac162a77fb78be360d9f771d36cbf1202e94fc6d70e284ad5db6ab72608"},
{file = "msgpack-1.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:bf8eedc7bfbf63cbc9abe58287c32d78780a347835e82c23033c68f11f80bb05"},
{file = "msgpack-1.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:03c5554315317d76c25a15569dd52ac6047b105df71e861f24faf9675672b72d"},
{file = "msgpack-1.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1d7ab166401f7789bf11262439336c0a01b878f0d602e48f35c35d2e3a555820"},
{file = "msgpack-1.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:7b50afd767cc053ad92fad39947c3670db27305fd1c49acded44d9d9ac8b56fd"},
{file = "msgpack-1.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99ea9e65876546743b2b8bb5bc7adefbb03b9da78a899827467da197a48f790b"},
{file = "msgpack-1.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:0968b368a9a9081435bfcb7a57a1e8b75c7bf038ef911b369acd2e038c7f873a"},
{file = "msgpack-1.0.1-cp36-cp36m-win32.whl", hash = "sha256:decf2091b75987ca2564e3b742f9614eb7d57e39ff04eaa68af7a3fc5648f7ed"},
{file = "msgpack-1.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:c4e5f96a1d0d916ce7a16decb7499e8923ddef007cf7d68412fb68767766648a"},
{file = "msgpack-1.0.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d113c6b1239c62669ef3063693842605a3edbfebc39a333cf91ba60d314afe6d"},
{file = "msgpack-1.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:69f6aa503378548ea1e760c11aeb6fc91952bf3634fd806a38a0e47edb507fcd"},
{file = "msgpack-1.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ce4ebe2c79411cd5671b20862831880e7850a2de699cff6626f48853fde61ae6"},
{file = "msgpack-1.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d76672602db16e3f44bc1a85c7ee5f15d79e02fcf5bc9d133c2954753be6eddc"},
{file = "msgpack-1.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:b5b27923b6c98a2616b7e906a29e4e10e1b4424aea87a0e0d5636327dc6ea315"},
{file = "msgpack-1.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:20196229acc193939223118c7420838749d5b0cece49cd397739a3a6ffcfe2d1"},
{file = "msgpack-1.0.1-cp37-cp37m-win32.whl", hash = "sha256:c60e8b2bf754b8dcc1075c5bee0b177ed9193e7cbd2377faaf507120a948e697"},
{file = "msgpack-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:29a6fb3729215b6fcab786ef4f460a5406a5c056f7021191f70ff7712a3f6ba4"},
{file = "msgpack-1.0.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:e13b9007af66a3f62574bc0a13843df0e4402f5ee4b00a02aa1803f01d26b9fb"},
{file = "msgpack-1.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d3cea07ad16919a44e8d1ea67efa5244855cdce807d672f41694acc24d08834e"},
{file = "msgpack-1.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1e8d27bac821f8aa909904a704a67e5e8bc2e42b153415fc3621b7afbc06702b"},
{file = "msgpack-1.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:35cbefa7d7bddfb4b0770a1b9ff721cd8dfe9a680947a68457974d5e3e6acc2f"},
{file = "msgpack-1.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:2933443313289725f16bd7b99a8c3aa6a2cca1549e661d7407f056a0af80bf7b"},
{file = "msgpack-1.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f20d7d4f1f0728560408ba6933154abccf0c20f24642a2404b43d5c23e4119ab"},
{file = "msgpack-1.0.1-cp38-cp38-win32.whl", hash = "sha256:b107f9b36665bf7d7c6176a938a361a7aba16aa179d833919448f77287866484"},
{file = "msgpack-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e234ff83628ca3ab345bf97fb36ccbf6d2f1700f5e08868643bf4489edc960f8"},
{file = "msgpack-1.0.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:abcc62303ac4d789878d4aac4cdba1bbe2adb478d67be99cd4a6d56ac3a4028f"},
{file = "msgpack-1.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4e58b9f4a99bc3a90859bb006ec4422448a5ce39e5cd6e7498c56de5dcec9c34"},
{file = "msgpack-1.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1fc9f21da9fd77088ebfd3c9941b044ca3f4a048e85f7ff5727f26bcdbffed61"},
{file = "msgpack-1.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:40dd1ac7420f071e96b3e4a4a7b8e69546a6f8065ff5995dbacf53f86207eb98"},
{file = "msgpack-1.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:66d47e952856bfcde46d8351380d0b5b928a73112b66bc06d5367dfcc077c06a"},
{file = "msgpack-1.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:01835e300967e5ad6fdbfc36eafe74df67ff47e16e0d6dee8766630550315903"},
{file = "msgpack-1.0.1-cp39-cp39-win32.whl", hash = "sha256:f08d9dd3ce0c5e972dc4653f0fb66d2703941e65356388c13032b578dd718261"},
{file = "msgpack-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:c144ff4954a6ea40aa603600c8be175349588fc68696092889fa34ab6e055060"},
{file = "msgpack-1.0.1.tar.gz", hash = "sha256:7033215267a0e9f60f4a5e4fb2228a932c404f237817caff8dc3115d9e7cd975"},
]
mypy = [
{file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"},
@@ -1472,8 +1483,8 @@ nodeenv = [
{file = "nodeenv-1.5.0.tar.gz", hash = "sha256:ab45090ae383b716c4ef89e690c41ff8c2b257b85b309f01f3654df3d084bd7c"},
]
packaging = [
{file = "packaging-20.7-py2.py3-none-any.whl", hash = "sha256:eb41423378682dadb7166144a4926e443093863024de508ca5c9737d6bc08376"},
{file = "packaging-20.7.tar.gz", hash = "sha256:05af3bb85d320377db281cf254ab050e1a7ebcbf5410685a9a407e18a1f81236"},
{file = "packaging-20.8-py2.py3-none-any.whl", hash = "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858"},
{file = "packaging-20.8.tar.gz", hash = "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"},
]
parso = [
{file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"},
@@ -1516,12 +1527,12 @@ poetry-core = [
{file = "poetry_core-1.0.0-py2.py3-none-any.whl", hash = "sha256:769288e0e1b88dfcceb3185728f0b7388b26d5f93d6c22d2dcae372da51d200d"},
]
pre-commit = [
{file = "pre_commit-2.9.2-py2.py3-none-any.whl", hash = "sha256:949b13efb7467ae27e2c8f9e83434dacf2682595124d8902554a4e18351e5781"},
{file = "pre_commit-2.9.2.tar.gz", hash = "sha256:e31c04bc23741194a7c0b983fe512801e151a0638c6001c49f2bd034f8a664a1"},
{file = "pre_commit-2.9.3-py2.py3-none-any.whl", hash = "sha256:6c86d977d00ddc8a60d68eec19f51ef212d9462937acf3ea37c7adec32284ac0"},
{file = "pre_commit-2.9.3.tar.gz", hash = "sha256:ee784c11953e6d8badb97d19bc46b997a3a9eded849881ec587accd8608d74a4"},
]
pre-commit-hooks = [
{file = "pre_commit_hooks-3.3.0-py2.py3-none-any.whl", hash = "sha256:2190d72ac867bd9b8880de32d9304ec54182c89720cce56f22742890ed8ba90f"},
{file = "pre_commit_hooks-3.3.0.tar.gz", hash = "sha256:1e18c0451279fb88653c7b9f8fd73ccc35925e95b636c5b64095538f68a23b06"},
{file = "pre_commit_hooks-3.4.0-py2.py3-none-any.whl", hash = "sha256:b1d329fc712f53f56af7c4a0ac08c414a7fcfd634dbd829c3a03f39cfb9c3574"},
{file = "pre_commit_hooks-3.4.0.tar.gz", hash = "sha256:57e377b931aceead550e4a7bdbe8065e79e371e80f593b5b6d1129e63a77154f"},
]
prompt-toolkit = [
{file = "prompt_toolkit-3.0.8-py3-none-any.whl", hash = "sha256:7debb9a521e0b1ee7d2fe96ee4bd60ef03c6492784de0547337ca4433e46aa63"},
@@ -1540,8 +1551,8 @@ pycparser = [
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
]
pygments = [
{file = "Pygments-2.7.2-py3-none-any.whl", hash = "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"},
{file = "Pygments-2.7.2.tar.gz", hash = "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0"},
{file = "Pygments-2.7.3-py3-none-any.whl", hash = "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"},
{file = "Pygments-2.7.3.tar.gz", hash = "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716"},
]
pylev = [
{file = "pylev-1.3.0-py2.py3-none-any.whl", hash = "sha256:1d29a87beb45ebe1e821e7a3b10da2b6b2f4c79b43f482c2df1a1f748a6e114e"},
@@ -1556,8 +1567,8 @@ pyparsing = [
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
]
pytest = [
{file = "pytest-6.1.2-py3-none-any.whl", hash = "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe"},
{file = "pytest-6.1.2.tar.gz", hash = "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e"},
{file = "pytest-6.2.1-py3-none-any.whl", hash = "sha256:1969f797a1a0dbd8ccf0fecc80262312729afea9c17f1d70ebf85c5e76c6f7c8"},
{file = "pytest-6.2.1.tar.gz", hash = "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"},
]
pytest-cov = [
{file = "pytest-cov-2.10.1.tar.gz", hash = "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e"},
@@ -1630,8 +1641,8 @@ reorder-python-imports = [
{file = "reorder_python_imports-2.3.6.tar.gz", hash = "sha256:2ea16d2253536e7f90427b383cd046e46977ca25aae82464883eee882bc7d21b"},
]
requests = [
{file = "requests-2.25.0-py2.py3-none-any.whl", hash = "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"},
{file = "requests-2.25.0.tar.gz", hash = "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8"},
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
]
requests-toolbelt = [
{file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"},
@@ -1756,8 +1767,8 @@ urllib3 = [
{file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"},
]
virtualenv = [
{file = "virtualenv-20.2.1-py2.py3-none-any.whl", hash = "sha256:07cff122e9d343140366055f31be4dcd61fd598c69d11cd33a9d9c8df4546dd7"},
{file = "virtualenv-20.2.1.tar.gz", hash = "sha256:e0aac7525e880a429764cefd3aaaff54afb5d9f25c82627563603f5d7de5a6e5"},
{file = "virtualenv-20.2.2-py2.py3-none-any.whl", hash = "sha256:54b05fc737ea9c9ee9f8340f579e5da5b09fb64fd010ab5757eb90268616907c"},
{file = "virtualenv-20.2.2.tar.gz", hash = "sha256:b7a8ec323ee02fb2312f098b6b4c9de99559b462775bc8fe3627a73706603c1b"},
]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "tox-poetry-installer"
version = "0.6.2"
version = "0.6.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"
@@ -39,7 +39,7 @@ poetry = ["poetry"]
python = "^3.6.1"
poetry = {version = "^1.0.0", optional = true}
poetry-core = "^1.0.0"
tox = "^3.0.0"
tox = "^3.8.0"
[tool.poetry.dev-dependencies]
bandit = "^1.6.2"

View File

@@ -1,7 +1,7 @@
# pylint: disable=missing-docstring
__title__ = "tox-poetry-installer"
__summary__ = "Tox plugin to install Tox environment dependencies using the Poetry backend and lockfile"
__version__ = "0.6.2"
__version__ = "0.6.3"
__url__ = "https://github.com/enpaul/tox-poetry-installer/"
__license__ = "MIT"
__authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]

View File

@@ -19,7 +19,7 @@ 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__}]:"
REPORTER_PREFIX: str = f"{__about__.__title__}:"
# Semver compatible version of the current python platform version. Used for checking

View File

@@ -4,12 +4,9 @@ All implementations of tox hooks are defined here, as well as any single-use hel
specifically related to implementing the hooks (to keep the size/readability of the hook functions
themselves manageable).
"""
from typing import List
from typing import Optional
from poetry.core.packages import Package as PoetryPackage
from tox import hookimpl
from tox import reporter
import tox
from tox.action import Action as ToxAction
from tox.config import Parser as ToxParser
from tox.venv import VirtualEnv as ToxVirtualEnv
@@ -17,11 +14,12 @@ from tox.venv import VirtualEnv as ToxVirtualEnv
from tox_poetry_installer import __about__
from tox_poetry_installer import constants
from tox_poetry_installer import exceptions
from tox_poetry_installer import installer
from tox_poetry_installer import utilities
from tox_poetry_installer.datatypes import PackageMap
@hookimpl
@tox.hookimpl
def tox_addoption(parser: ToxParser):
"""Add required configuration options to the tox INI file
@@ -57,7 +55,7 @@ def tox_addoption(parser: ToxParser):
)
@hookimpl
@tox.hookimpl
def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional[bool]:
"""Install the dependencies for the current environment
@@ -77,74 +75,76 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional
and venv.envconfig.config.option.require_poetry
):
venv.status = err.__class__.__name__
reporter.error(str(err))
tox.reporter.error(str(err))
return False
reporter.verbosity1(str(err))
tox.reporter.verbosity1(str(err))
return None
reporter.verbosity1(
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Loaded project pyproject.toml from {poetry.file}"
)
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}"
)
try:
if venv.envconfig.require_locked_deps and venv.envconfig.deps:
raise exceptions.LockedDepsRequiredError(
f"Unlocked dependencies '{venv.envconfig.deps}' specified for environment '{venv.name}' which requires locked dependencies"
)
package_map: PackageMap = {
packages: PackageMap = {
package.name: package
for package in poetry.locker.locked_repository(True).packages
}
if venv.envconfig.install_dev_deps:
dev_deps: List[PoetryPackage] = [
dep
for dep in package_map.values()
if dep not in poetry.locker.locked_repository(False).packages
]
dev_deps = utilities.find_dev_deps(packages, poetry)
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Identified {len(dev_deps)} development dependencies to install to env"
)
else:
dev_deps = []
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Env does not install development dependencies, skipping"
)
reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Identified {len(dev_deps)} development dependencies to install to env"
env_deps = utilities.find_additional_deps(
packages, poetry, venv.envconfig.locked_deps
)
env_deps: List[PoetryPackage] = []
for dep in venv.envconfig.locked_deps:
env_deps += utilities.find_transients(
package_map, dep.lower(), allow_missing=[poetry.package.name]
)
reporter.verbosity1(
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Identified {len(env_deps)} environment dependencies to install to env"
)
if not venv.envconfig.skip_install and not venv.envconfig.config.skipsdist:
project_deps: List[PoetryPackage] = utilities.find_project_dependencies(
venv, poetry, package_map
project_deps = utilities.find_project_deps(
packages, poetry, venv.envconfig.extras
)
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Identified {len(project_deps)} project dependencies to install to env"
)
else:
project_deps = []
reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Skipping installation of project dependencies, env does not install project package"
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Env does not install project package, skipping"
)
reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Identified {len(project_deps)} project dependencies to install to env"
)
except exceptions.ToxPoetryInstallerException as err:
venv.status = err.__class__.__name__
reporter.error(f"{constants.REPORTER_PREFIX} {err}")
tox.reporter.error(f"{constants.REPORTER_PREFIX} {err}")
return False
except Exception as err:
venv.status = "InternalError"
reporter.error(f"{constants.REPORTER_PREFIX} Internal plugin error: {err}")
tox.reporter.error(f"{constants.REPORTER_PREFIX} Internal plugin error: {err}")
raise err
dependencies = list(set(dev_deps + env_deps + project_deps))
dependencies = dev_deps + env_deps + project_deps
action.setactivity(
__about__.__title__,
f"Installing {len(dependencies)} dependencies from Poetry lock file",
)
utilities.install_to_venv(poetry, venv, dependencies)
installer.install(poetry, venv, dependencies)
return venv.envconfig.require_locked_deps or None

View File

@@ -0,0 +1,53 @@
"""Funcationality for performing virtualenv installation"""
# 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 typing
from pathlib import Path
from typing import Sequence
from typing import Set
import tox
from poetry.core.packages import Package as PoetryPackage
from tox.venv import VirtualEnv as ToxVirtualEnv
from tox_poetry_installer import constants
if typing.TYPE_CHECKING:
from tox_poetry_installer import _poetry
def install(
poetry: "_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
"""
from tox_poetry_installer import _poetry
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Installing {len(packages)} packages to environment at {venv.envconfig.envdir}"
)
pip = _poetry.PipInstaller(
env=_poetry.VirtualEnv(path=Path(venv.envconfig.envdir)),
io=_poetry.NullIO(),
pool=poetry.pool,
)
installed: Set[PoetryPackage] = set()
for dependency in packages:
if dependency not in installed:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Installing {dependency}"
)
pip.install(dependency)
installed.add(dependency)
else:
tox.reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Already installed {dependency}, skipping"
)

View File

@@ -4,13 +4,12 @@
# 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
import tox
from poetry.core.packages import Package as PoetryPackage
from tox import reporter
from tox.action import Action as ToxAction
from tox.venv import VirtualEnv as ToxVirtualEnv
@@ -22,127 +21,6 @@ if typing.TYPE_CHECKING:
from tox_poetry_installer import _poetry
def install_to_venv(
poetry: "_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
"""
from tox_poetry_installer import _poetry
reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Installing {len(packages)} packages to environment at {venv.envconfig.envdir}"
)
installer = _poetry.PipInstaller(
env=_poetry.VirtualEnv(path=Path(venv.envconfig.envdir)),
io=_poetry.NullIO(),
pool=poetry.pool,
)
for dependency in packages:
reporter.verbosity1(f"{constants.REPORTER_PREFIX} Installing {dependency}")
installer.install(dependency)
def find_transients(
packages: PackageMap, dependency_name: str, allow_missing: Sequence[str] = ()
) -> Set[PoetryPackage]:
"""Using a poetry object identify all dependencies of a specific dependency
:param packages: All packages from the lockfile to use for identifying dependency relationships.
:param dependency_name: Bare name (without version) of the dependency to fetch the transient
dependencies of.
:param allow_missing: Sequence of package names to allow to be missing from the lockfile. Any
packages that are not found in the lockfile but their name appears in this
list will be silently skipped from installation.
:returns: List of packages that need to be installed for the requested dependency.
.. note:: The package corresponding to the dependency named by ``dependency_name`` is included
in the list of returned packages.
"""
from tox_poetry_installer import _poetry
def find_deps_of_deps(name: str, searched: Set[str]) -> PackageMap:
searched.add(name)
if name in _poetry.Provider.UNSAFE_PACKAGES:
reporter.warning(
f"{constants.REPORTER_PREFIX} Installing package '{name}' using Poetry is not supported and will be skipped"
)
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {name}: designated unsafe by Poetry"
)
return dict()
transients: PackageMap = {}
try:
package = packages[name]
except KeyError as err:
if name in allow_missing:
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {name}: package is not in lockfile but designated as allowed to be missing"
)
return dict()
raise err
if not package.python_constraint.allows(constants.PLATFORM_VERSION):
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:
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Skip {package}: incompatible platform requirement '{package.platform}' for current platform '{sys.platform}'"
)
else:
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Including {package} for installation"
)
transients[name] = package
for index, dep in enumerate(package.requires):
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Processing dependency {index + 1}/{len(package.requires)} for {package}: {dep.name}"
)
if dep.name not in searched:
transients.update(find_deps_of_deps(dep.name, searched))
else:
reporter.verbosity2(
f"{constants.REPORTER_PREFIX} Package with name '{dep.name}' has already been processed, skipping"
)
return transients
searched: Set[str] = set()
try:
transients: PackageMap = find_deps_of_deps(
packages[dependency_name].name, searched
)
except KeyError:
if dependency_name in _poetry.Provider.UNSAFE_PACKAGES:
reporter.warning(
f"{constants.REPORTER_PREFIX} Installing package '{dependency_name}' using Poetry is not supported and will be skipped"
)
return set()
if any(
delimiter in dependency_name
for delimiter in constants.PEP508_VERSION_DELIMITERS
):
raise exceptions.LockedDepVersionConflictError(
f"Locked dependency '{dependency_name}' cannot include version specifier"
) from None
raise exceptions.LockedDepNotFoundError(
f"No version of locked dependency '{dependency_name}' found in the project lockfile"
) from None
return set(transients.values())
def check_preconditions(venv: ToxVirtualEnv, action: ToxAction) -> "_poetry.Poetry":
"""Check that the local project environment meets expectations"""
# Skip running the plugin for the provisioning environment. The provisioned environment,
@@ -178,42 +56,169 @@ def check_preconditions(venv: ToxVirtualEnv, action: ToxAction) -> "_poetry.Poet
) from None
def find_project_dependencies(
venv: ToxVirtualEnv, poetry: "_poetry.Poetry", packages: PackageMap
def identify_transients(
packages: PackageMap, dep_name: str, allow_missing: Sequence[str] = ()
) -> List[PoetryPackage]:
"""Install the dependencies of the project package
"""Using a pool of packages, identify all transient dependencies of a given package name
Install all primary dependencies of the project package.
:param packages: All packages from the lockfile to use for identifying dependency relationships.
:param dep_name: Bare name (without version) of the dependency to fetch the transient
dependencies of.
:param allow_missing: Sequence of package names to allow to be missing from the lockfile. Any
packages that are not found in the lockfile but their name appears in this
list will be silently skipped from installation.
:returns: List of packages that need to be installed for the requested dependency.
:param venv: Tox virtual environment to install the packages to
:param poetry: Poetry object the packages were sourced from
:param packages: Mapping of package names to the corresponding package object
.. note:: The package corresponding to the dependency named by ``dep_name`` is included
in the list of returned packages.
"""
from tox_poetry_installer import _poetry
transients: List[PoetryPackage] = []
searched: Set[PoetryPackage] = set()
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"
)
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}'"
)
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"
)
transients.append(package)
try:
find_deps_of_deps(packages[dep_name].name)
except KeyError:
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"
)
return []
if any(
delimiter in dep_name for delimiter in constants.PEP508_VERSION_DELIMITERS
):
raise exceptions.LockedDepVersionConflictError(
f"Locked dependency '{dep_name}' cannot include version specifier"
) from None
raise exceptions.LockedDepNotFoundError(
f"No version of locked dependency '{dep_name}' found in the project lockfile"
) from None
return transients
def find_project_deps(
packages: PackageMap, poetry: "_poetry.Poetry", extras: Sequence[str] = ()
) -> List[PoetryPackage]:
"""Find the root project dependencies
Recursively identify the dependencies of the root project package
:param packages: Mapping of all locked package names to their corresponding package object
:param poetry: Poetry object for the current project
:param extras: Sequence of extra names to include the dependencies of
"""
base_dependencies: List[PoetryPackage] = [
base_deps: List[PoetryPackage] = [
packages[item.name]
for item in poetry.package.requires
if not item.is_optional()
]
extra_dependencies: List[PoetryPackage] = []
for extra in venv.envconfig.extras:
reporter.verbosity1(
extra_deps: List[PoetryPackage] = []
for extra in extras:
tox.reporter.verbosity1(
f"{constants.REPORTER_PREFIX} Processing project extra '{extra}'"
)
try:
extra_dependencies += [
packages[item.name] for item in poetry.package.extras[extra]
]
extra_deps += [packages[item.name] for item in poetry.package.extras[extra]]
except KeyError:
raise exceptions.ExtraNotFoundError(
f"Environment '{venv.name}' specifies project extra '{extra}' which was not found in the lockfile"
f"Environment specifies project extra '{extra}' which was not found in the lockfile"
) from None
dependencies: List[PoetryPackage] = []
for dep in base_dependencies + extra_dependencies:
dependencies += find_transients(
for dep in base_deps + extra_deps:
dependencies += identify_transients(
packages, dep.name.lower(), allow_missing=[poetry.package.name]
)
return dependencies
def find_additional_deps(
packages: PackageMap, poetry: "_poetry.Poetry", dep_names: Sequence[str]
) -> List[PoetryPackage]:
"""Find additional dependencies
Recursively identify the dependencies of an arbitrary list of package names
:param packages: Mapping of all locked package names to their corresponding package object
:param poetry: Poetry object for the current project
:param dep_names: Sequence of additional dependency names to recursively find the transient
dependencies for
"""
deps: List[PoetryPackage] = []
for dep_name in dep_names:
deps += identify_transients(
packages, dep_name.lower(), allow_missing=[poetry.package.name]
)
return deps
def find_dev_deps(
packages: PackageMap, poetry: "_poetry.Poetry"
) -> List[PoetryPackage]:
"""Find the dev dependencies
Recursively identify the Poetry dev dependencies
:param packages: Mapping of all locked package names to their corresponding package object
:param poetry: Poetry object for the current project
"""
return find_additional_deps(
packages,
poetry,
poetry.pyproject.data["tool"]["poetry"].get("dev-dependencies", {}).keys(),
)