Skip to content

Allow users to provide version information to the required_plugins INI key #7366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/7346.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly we should include this in the changelog which added required_plugins, since it's the same release? (I'm OK either way)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong feelings for either as well, but I think splitting would document the multiple github issues that were used for the required_plugins feature better ( since we arrange them one issue per line item ). Otherwise, we don't have easy to follow documentation for what closed the linked issue

4 changes: 3 additions & 1 deletion doc/en/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1562,12 +1562,14 @@ passed multiple times. The expected format is ``name=value``. For example::
.. confval:: required_plugins

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

.. code-block:: ini

[pytest]
required_plugins = pytest-html pytest-xdist
required_plugins = pytest-django>=3.0.0,<4.0.0 pytest-html pytest-xdist>=1.0.0


.. confval:: testpaths
Expand Down
21 changes: 17 additions & 4 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1094,13 +1094,26 @@ def _validate_plugins(self) -> None:
if not required_plugins:
return

# Imported lazily to improve start-up time.
from packaging.version import Version
from packaging.requirements import InvalidRequirement, Requirement

plugin_info = self.pluginmanager.list_plugin_distinfo()
plugin_dist_names = [dist.project_name for _, dist in plugin_info]
plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info}

missing_plugins = []
for plugin in required_plugins:
if plugin not in plugin_dist_names:
missing_plugins.append(plugin)
for required_plugin in required_plugins:
spec = None
try:
spec = Requirement(required_plugin)
except InvalidRequirement:
missing_plugins.append(required_plugin)
continue

if spec.name not in plugin_dist_info:
missing_plugins.append(required_plugin)
elif Version(plugin_dist_info[spec.name]) not in spec.specifier:
missing_plugins.append(required_plugin)

if missing_plugins:
fail(
Expand Down
57 changes: 57 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,63 @@ def test_invalid_ini_keys(
),
(
"""
[pytest]
required_plugins = pytest-xdist
""",
"",
),
(
"""
[pytest]
required_plugins = pytest-xdist==1.32.0
""",
"",
),
(
"""
[pytest]
required_plugins = pytest-xdist>1.0.0,<2.0.0
""",
"",
),
(
"""
[pytest]
required_plugins = pytest-xdist~=1.32.0 pytest-xdist==1.32.0 pytest-xdist!=0.0.1 pytest-xdist<=99.99.0
pytest-xdist>=1.32.0 pytest-xdist<9.9.9 pytest-xdist>1.30.0 pytest-xdist===1.32.0
""",
"",
),
(
"""
[pytest]
required_plugins = pytest-xdist>9.9.9 pytest-xdist==1.32.0 pytest-xdist==8.8.8
""",
"Missing required plugins: pytest-xdist==8.8.8, pytest-xdist>9.9.9",
),
(
"""
[pytest]
required_plugins = pytest-xdist==aegsrgrsgs pytest-xdist==-1 pytest-xdist>2.1.1,>3.0.0
""",
"Missing required plugins: pytest-xdist==-1, pytest-xdist==aegsrgrsgs, pytest-xdist>2.1.1,>3.0.0",
),
(
"""
[pytest]
required_plugins = pytest-xdist== pytest-xdist<=
""",
"Missing required plugins: pytest-xdist<=, pytest-xdist==",
),
(
"""
[pytest]
required_plugins = pytest-xdist= pytest-xdist<
""",
"Missing required plugins: pytest-xdist<, pytest-xdist=",
),
(
"""
[some_other_header]
required_plugins = wont be triggered
[pytest]
Expand Down