Skip to content

Commit 4e5a7b7

Browse files
Merge pull request #7366 from gnikonorov/issue_7346
Allow users to provide version information to the required_plugins INI key
2 parents 06489d2 + 3206255 commit 4e5a7b7

File tree

4 files changed

+78
-5
lines changed

4 files changed

+78
-5
lines changed

changelog/7346.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Version information as defined by `PEP 440 <https://www.python.org/dev/peps/pep-0440/#version-specifiers>`_ may now be included when providing plugins to the ``required_plugins`` configuration option.

doc/en/reference.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,12 +1562,14 @@ passed multiple times. The expected format is ``name=value``. For example::
15621562
.. confval:: required_plugins
15631563

15641564
A space separated list of plugins that must be present for pytest to run.
1565+
Plugins can be listed with or without version specifiers directly following
1566+
their name. Whitespace between different version specifiers is not allowed.
15651567
If any one of the plugins is not found, emit an error.
15661568

15671569
.. code-block:: ini
15681570
15691571
[pytest]
1570-
required_plugins = pytest-html pytest-xdist
1572+
required_plugins = pytest-django>=3.0.0,<4.0.0 pytest-html pytest-xdist>=1.0.0
15711573
15721574
15731575
.. confval:: testpaths

src/_pytest/config/__init__.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,13 +1106,26 @@ def _validate_plugins(self) -> None:
11061106
if not required_plugins:
11071107
return
11081108

1109+
# Imported lazily to improve start-up time.
1110+
from packaging.version import Version
1111+
from packaging.requirements import InvalidRequirement, Requirement
1112+
11091113
plugin_info = self.pluginmanager.list_plugin_distinfo()
1110-
plugin_dist_names = [dist.project_name for _, dist in plugin_info]
1114+
plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info}
11111115

11121116
missing_plugins = []
1113-
for plugin in required_plugins:
1114-
if plugin not in plugin_dist_names:
1115-
missing_plugins.append(plugin)
1117+
for required_plugin in required_plugins:
1118+
spec = None
1119+
try:
1120+
spec = Requirement(required_plugin)
1121+
except InvalidRequirement:
1122+
missing_plugins.append(required_plugin)
1123+
continue
1124+
1125+
if spec.name not in plugin_dist_info:
1126+
missing_plugins.append(required_plugin)
1127+
elif Version(plugin_dist_info[spec.name]) not in spec.specifier:
1128+
missing_plugins.append(required_plugin)
11161129

11171130
if missing_plugins:
11181131
fail(

testing/test_config.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,63 @@ def test_invalid_ini_keys(
250250
),
251251
(
252252
"""
253+
[pytest]
254+
required_plugins = pytest-xdist
255+
""",
256+
"",
257+
),
258+
(
259+
"""
260+
[pytest]
261+
required_plugins = pytest-xdist==1.32.0
262+
""",
263+
"",
264+
),
265+
(
266+
"""
267+
[pytest]
268+
required_plugins = pytest-xdist>1.0.0,<2.0.0
269+
""",
270+
"",
271+
),
272+
(
273+
"""
274+
[pytest]
275+
required_plugins = pytest-xdist~=1.32.0 pytest-xdist==1.32.0 pytest-xdist!=0.0.1 pytest-xdist<=99.99.0
276+
pytest-xdist>=1.32.0 pytest-xdist<9.9.9 pytest-xdist>1.30.0 pytest-xdist===1.32.0
277+
""",
278+
"",
279+
),
280+
(
281+
"""
282+
[pytest]
283+
required_plugins = pytest-xdist>9.9.9 pytest-xdist==1.32.0 pytest-xdist==8.8.8
284+
""",
285+
"Missing required plugins: pytest-xdist==8.8.8, pytest-xdist>9.9.9",
286+
),
287+
(
288+
"""
289+
[pytest]
290+
required_plugins = pytest-xdist==aegsrgrsgs pytest-xdist==-1 pytest-xdist>2.1.1,>3.0.0
291+
""",
292+
"Missing required plugins: pytest-xdist==-1, pytest-xdist==aegsrgrsgs, pytest-xdist>2.1.1,>3.0.0",
293+
),
294+
(
295+
"""
296+
[pytest]
297+
required_plugins = pytest-xdist== pytest-xdist<=
298+
""",
299+
"Missing required plugins: pytest-xdist<=, pytest-xdist==",
300+
),
301+
(
302+
"""
303+
[pytest]
304+
required_plugins = pytest-xdist= pytest-xdist<
305+
""",
306+
"Missing required plugins: pytest-xdist<, pytest-xdist=",
307+
),
308+
(
309+
"""
253310
[some_other_header]
254311
required_plugins = wont be triggered
255312
[pytest]

0 commit comments

Comments
 (0)