Skip to content

Commit

Permalink
Add dependencies from lockfile
Browse files Browse the repository at this point in the history
GitHub: #24
  • Loading branch information
sinoroc committed Oct 12, 2020
1 parent 1b35c68 commit a25ac03
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 11 deletions.
17 changes: 15 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,24 @@ It is a plugin for Tox and it is available on PyPI, install it however best fits
By default the plugin does not do anything. Use one of the following settings to activate the corresponding features.


``poetry_experimental_add_locked_dependencies``
-----------------------------------------------

Set the ``testenv`` setting ``poetry_experimental_add_locked_dependencies`` to ``True`` to let Tox add Poetry's locked dependencies from the *lockfile* to the ``deps`` list in the test environment.

.. code::
[testenv:example]
# ...
poetry_experimental_add_locked_dependencies = True
If ``add_poetry_dev_dependencies`` is set as well then the development dependencies are added with the version from the *lockfile*.


``add_poetry_dev_dependencies``
-------------------------------

Set the ``testenv`` setting ``add_poetry_dev_dependencies`` to ``True`` to let Tox install Poetry's development dependencies in the test environment.
Set the ``testenv`` setting ``add_poetry_dev_dependencies`` to ``True`` to let Tox add Poetry's development dependencies to the ``deps`` list in the test environment.

.. code::
Expand All @@ -54,7 +68,6 @@ Set the ``testenv`` setting ``add_poetry_dev_dependencies`` to ``True`` to let T
add_poetry_dev_dependencies = True
``poetry_use_source_repos``
---------------------------

Expand Down
3 changes: 3 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ ignore_missing_imports = True
[mypy-setuptools.*]
ignore_missing_imports = True

[mypy-tomlkit.*]
ignore_missing_imports = True

[mypy-tox.*]
ignore_missing_imports = True

Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ url = https://pypi.org/project/tox-poetry-dev-dependencies/
install_requires =
importlib-metadata
poetry-core ~= 1.0
tomlkit
tox
package_dir =
= src
Expand Down
79 changes: 70 additions & 9 deletions src/tox_poetry_dev_dependencies/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import typing

import poetry.core.factory
import tomlkit
import tox

if typing.TYPE_CHECKING:
Expand All @@ -17,6 +18,8 @@
PIP_DEFAULT_INDEX_SERVER_URL = 'https://pypi.org/simple'
PIP_DEFAULT_INDEX_SERVER_NAME = 'pypi'

POETRY_LOCKFILE_FILE_NAME = 'poetry.lock'


class _Exception(Exception):
"""Base exception."""
Expand Down Expand Up @@ -47,15 +50,24 @@ def tox_addoption(parser: tox.config.Parser) -> None:
'poetry_use_source_repos',
'string',
(
"Use Poetry's source repositories. Set 'pip_env_vars' to set as "
"Pip environment variables ('PIP_INDEX_URL', and "
"'PIP_EXTRA_INDEX_URL')."
"Use Poetry's source repositories. Set 'pip_env_vars' to set as"
" Pip environment variables ('PIP_INDEX_URL' and"
" 'PIP_EXTRA_INDEX_URL')."
),
)
parser.add_testenv_attribute(
'poetry_experimental_no_virtual_env',
'bool',
"Do not create a virtual environment.",
"(EXPERIMENTAL) Do not create a virtual environment.",
default=False,
)
parser.add_testenv_attribute(
'poetry_experimental_add_locked_dependencies',
'bool',
(
"(EXPERIMENTAL) Add Poetry's locked dependencies from the lockfile"
" to 'deps' in the test environment."
),
default=False,
)

Expand Down Expand Up @@ -99,11 +111,18 @@ def _is_test_env(env_config: tox.config.TestenvConfig) -> bool:
@tox.hookimpl # type: ignore[misc]
def tox_configure(config: tox.config.Config) -> None:
"""Set hook."""
#
project_dir_path = pathlib.Path(config.setupdir)
#
try:
poetry_ = _get_poetry(config.setupdir)
poetry_ = _get_poetry(project_dir_path)
except (NoPoetryFound, NoPyprojectTomlFound):
pass
else:
#
locked_deps = _get_locked_deps(project_dir_path)
_add_locked_dependencies(config, locked_deps)
#
dev_deps = _get_dev_requirements(poetry_)
_add_dev_dependencies(config, dev_deps)
#
Expand Down Expand Up @@ -144,10 +163,11 @@ def _add_dev_dependencies(
) -> None:
#
for env_config in tox_config.envconfigs.values():
if _is_test_env(env_config):
if env_config.add_poetry_dev_dependencies is True:
for dep_config in dev_dep_configs:
env_config.deps.append(dep_config)
if env_config.poetry_experimental_add_locked_dependencies is not True:
if _is_test_env(env_config):
if env_config.add_poetry_dev_dependencies is True:
for dep_config in dev_dep_configs:
env_config.deps.append(dep_config)


def _add_index_servers(
Expand Down Expand Up @@ -179,6 +199,21 @@ def _add_index_servers_as_pip_env_vars(
)


def _add_locked_dependencies(
tox_config: tox.config.Config,
locked_deps: typing.Mapping[str, typing.List[tox.config.DepConfig]],
) -> None:
#
for env_config in tox_config.envconfigs.values():
if _is_test_env(env_config):
if env_config.poetry_experimental_add_locked_dependencies is True:
for dep_config in locked_deps['main']:
env_config.deps.append(dep_config)
if env_config.add_poetry_dev_dependencies is True:
for dep_config in locked_deps['dev']:
env_config.deps.append(dep_config)


def _get_poetry(project_root_path: pathlib.Path) -> poetry.core.poetry.Poetry:
poetry_factory = poetry.core.factory.Factory()
try:
Expand Down Expand Up @@ -257,4 +292,30 @@ def _get_index_servers(
return index_servers


def _get_locked_deps(
project_root_path: pathlib.Path,
) -> typing.Dict[str, typing.List[tox.config.DepConfig]]:
#
locked_deps: typing.Dict[str, typing.List[tox.config.DepConfig]] = {}
#
lock_file_path = project_root_path.joinpath(POETRY_LOCKFILE_FILE_NAME)
if lock_file_path.is_file():
#
lock_str = lock_file_path.read_text()
lock_document = tomlkit.parse(lock_str)
#
for dependency in lock_document['package']:
#
dep_name = dependency['name']
dep_version = dependency['version']
#
dep_pep_508 = f'{dep_name}=={dep_version}'
#
dep_category = dependency['category']
dep_config = tox.config.DepConfig(dep_pep_508)
locked_deps.setdefault(dep_category, []).append(dep_config)
#
return locked_deps


# EOF

0 comments on commit a25ac03

Please sign in to comment.