Skip to content

Commit 0f60884

Browse files
committed
Allow adding dependencies from lockfile
GitHub: #24
1 parent 1b35c68 commit 0f60884

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
0.0.4.dev0
77
==========
88

9+
* Add the ``poetry_experimental_add_locked_dependencies`` setting to let Tox add Poetry's locked dependencies from Poetry's lockfile (experimental feature).
10+
911

1012
0.0.3
1113
=====

README.rst

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,24 @@ It is a plugin for Tox and it is available on PyPI, install it however best fits
4242
By default the plugin does not do anything. Use one of the following settings to activate the corresponding features.
4343

4444

45+
``poetry_experimental_add_locked_dependencies``
46+
-----------------------------------------------
47+
48+
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.
49+
50+
.. code::
51+
52+
[testenv:example]
53+
# ...
54+
poetry_experimental_add_locked_dependencies = True
55+
56+
If ``add_poetry_dev_dependencies`` is set as well then the development dependencies are added with the version from the *lockfile*.
57+
58+
4559
``add_poetry_dev_dependencies``
4660
-------------------------------
4761

48-
Set the ``testenv`` setting ``add_poetry_dev_dependencies`` to ``True`` to let Tox install Poetry's development dependencies in the test environment.
62+
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.
4963

5064
.. code::
5165
@@ -54,7 +68,6 @@ Set the ``testenv`` setting ``add_poetry_dev_dependencies`` to ``True`` to let T
5468
add_poetry_dev_dependencies = True
5569
5670
57-
5871
``poetry_use_source_repos``
5972
---------------------------
6073

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ ignore_missing_imports = True
1919
[mypy-setuptools.*]
2020
ignore_missing_imports = True
2121

22+
[mypy-tomlkit.*]
23+
ignore_missing_imports = True
24+
2225
[mypy-tox.*]
2326
ignore_missing_imports = True
2427

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ url = https://pypi.org/project/tox-poetry-dev-dependencies/
3535
install_requires =
3636
importlib-metadata
3737
poetry-core ~= 1.0
38+
tomlkit
3839
tox
3940
package_dir =
4041
= src

src/tox_poetry_dev_dependencies/_hooks.py

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import typing
77

88
import poetry.core.factory
9+
import tomlkit
910
import tox
1011

1112
if typing.TYPE_CHECKING:
@@ -17,6 +18,8 @@
1718
PIP_DEFAULT_INDEX_SERVER_URL = 'https://pypi.org/simple'
1819
PIP_DEFAULT_INDEX_SERVER_NAME = 'pypi'
1920

21+
POETRY_LOCKFILE_FILE_NAME = 'poetry.lock'
22+
2023

2124
class _Exception(Exception):
2225
"""Base exception."""
@@ -47,15 +50,24 @@ def tox_addoption(parser: tox.config.Parser) -> None:
4750
'poetry_use_source_repos',
4851
'string',
4952
(
50-
"Use Poetry's source repositories. Set 'pip_env_vars' to set as "
51-
"Pip environment variables ('PIP_INDEX_URL', and "
52-
"'PIP_EXTRA_INDEX_URL')."
53+
"Use Poetry's source repositories. Set 'pip_env_vars' to set as"
54+
" Pip environment variables ('PIP_INDEX_URL' and"
55+
" 'PIP_EXTRA_INDEX_URL')."
5356
),
5457
)
5558
parser.add_testenv_attribute(
5659
'poetry_experimental_no_virtual_env',
5760
'bool',
58-
"Do not create a virtual environment.",
61+
"(EXPERIMENTAL) Do not create a virtual environment.",
62+
default=False,
63+
)
64+
parser.add_testenv_attribute(
65+
'poetry_experimental_add_locked_dependencies',
66+
'bool',
67+
(
68+
"(EXPERIMENTAL) Add Poetry's locked dependencies from the lockfile"
69+
" to 'deps' in the test environment."
70+
),
5971
default=False,
6072
)
6173

@@ -99,11 +111,18 @@ def _is_test_env(env_config: tox.config.TestenvConfig) -> bool:
99111
@tox.hookimpl # type: ignore[misc]
100112
def tox_configure(config: tox.config.Config) -> None:
101113
"""Set hook."""
114+
#
115+
project_dir_path = pathlib.Path(config.setupdir)
116+
#
102117
try:
103-
poetry_ = _get_poetry(config.setupdir)
118+
poetry_ = _get_poetry(project_dir_path)
104119
except (NoPoetryFound, NoPyprojectTomlFound):
105120
pass
106121
else:
122+
#
123+
locked_deps = _get_locked_deps(project_dir_path)
124+
_add_locked_dependencies(config, locked_deps)
125+
#
107126
dev_deps = _get_dev_requirements(poetry_)
108127
_add_dev_dependencies(config, dev_deps)
109128
#
@@ -144,10 +163,11 @@ def _add_dev_dependencies(
144163
) -> None:
145164
#
146165
for env_config in tox_config.envconfigs.values():
147-
if _is_test_env(env_config):
148-
if env_config.add_poetry_dev_dependencies is True:
149-
for dep_config in dev_dep_configs:
150-
env_config.deps.append(dep_config)
166+
if env_config.poetry_experimental_add_locked_dependencies is not True:
167+
if _is_test_env(env_config):
168+
if env_config.add_poetry_dev_dependencies is True:
169+
for dep_config in dev_dep_configs:
170+
env_config.deps.append(dep_config)
151171

152172

153173
def _add_index_servers(
@@ -179,6 +199,21 @@ def _add_index_servers_as_pip_env_vars(
179199
)
180200

181201

202+
def _add_locked_dependencies(
203+
tox_config: tox.config.Config,
204+
locked_deps: typing.Mapping[str, typing.List[tox.config.DepConfig]],
205+
) -> None:
206+
#
207+
for env_config in tox_config.envconfigs.values():
208+
if _is_test_env(env_config):
209+
if env_config.poetry_experimental_add_locked_dependencies is True:
210+
for dep_config in locked_deps['main']:
211+
env_config.deps.append(dep_config)
212+
if env_config.add_poetry_dev_dependencies is True:
213+
for dep_config in locked_deps['dev']:
214+
env_config.deps.append(dep_config)
215+
216+
182217
def _get_poetry(project_root_path: pathlib.Path) -> poetry.core.poetry.Poetry:
183218
poetry_factory = poetry.core.factory.Factory()
184219
try:
@@ -257,4 +292,30 @@ def _get_index_servers(
257292
return index_servers
258293

259294

295+
def _get_locked_deps(
296+
project_root_path: pathlib.Path,
297+
) -> typing.Dict[str, typing.List[tox.config.DepConfig]]:
298+
#
299+
locked_deps: typing.Dict[str, typing.List[tox.config.DepConfig]] = {}
300+
#
301+
lock_file_path = project_root_path.joinpath(POETRY_LOCKFILE_FILE_NAME)
302+
if lock_file_path.is_file():
303+
#
304+
lock_str = lock_file_path.read_text()
305+
lock_document = tomlkit.parse(lock_str)
306+
#
307+
for dependency in lock_document['package']:
308+
#
309+
dep_name = dependency['name']
310+
dep_version = dependency['version']
311+
#
312+
dep_pep_508 = f'{dep_name}=={dep_version}'
313+
#
314+
dep_category = dependency['category']
315+
dep_config = tox.config.DepConfig(dep_pep_508)
316+
locked_deps.setdefault(dep_category, []).append(dep_config)
317+
#
318+
return locked_deps
319+
320+
260321
# EOF

0 commit comments

Comments
 (0)