From 6f8633cc17b6a54329febf81c76157a0d6d39621 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 13 Jun 2020 02:47:15 -0400 Subject: [PATCH 1/4] add in solution barring documentation --- .pre-commit-config.yaml | 12 +++---- src/_pytest/config/__init__.py | 21 ++++++++++--- testing/test_config.py | 57 ++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dc3717204..be4b16d61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,12 +42,12 @@ repos: - id: setup-cfg-fmt # TODO: when upgrading setup-cfg-fmt this can be removed args: [--max-py-version=3.9] -- repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.780 # NOTE: keep this in sync with setup.cfg. - hooks: - - id: mypy - files: ^(src/|testing/) - args: [] + #- repo: https://github.com/pre-commit/mirrors-mypy + #rev: v0.780 # NOTE: keep this in sync with setup.cfg. + #hooks: + #- id: mypy + #files: ^(src/|testing/) + #args: [] - repo: local hooks: - id: rst diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6e26bf15c..887744a03 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1088,13 +1088,26 @@ class Config: 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( diff --git a/testing/test_config.py b/testing/test_config.py index a10ac41dd..420fa06f8 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -250,6 +250,63 @@ class TestParseIni: ), ( """ + [pytest] + required_plugins = pytest-xdist + """, + "", + ), + ( + """ + [pytest] + required_plugins = pytest-xdist==1.32.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 + """, + "Missing required plugins: pytest-xdist==aegsrgrsgs", + ), + ( + """ + [pytest] + required_plugins = pytest-xdist==-1 + """, + "Missing required plugins: pytest-xdist==-1", + ), + ( + """ + [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] From f8a8bdbeb050533615be7ef517a0b5ca027bb5f4 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 13 Jun 2020 09:55:55 -0400 Subject: [PATCH 2/4] remove pre-commit change --- .pre-commit-config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be4b16d61..dc3717204 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,12 +42,12 @@ repos: - id: setup-cfg-fmt # TODO: when upgrading setup-cfg-fmt this can be removed args: [--max-py-version=3.9] - #- repo: https://github.com/pre-commit/mirrors-mypy - #rev: v0.780 # NOTE: keep this in sync with setup.cfg. - #hooks: - #- id: mypy - #files: ^(src/|testing/) - #args: [] +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.780 # NOTE: keep this in sync with setup.cfg. + hooks: + - id: mypy + files: ^(src/|testing/) + args: [] - repo: local hooks: - id: rst From 8a022c0ce3c76176961e07137100bee4d07f7572 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 13 Jun 2020 09:57:13 -0400 Subject: [PATCH 3/4] test to make sure precommit is fixed --- src/_pytest/config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 116383a73..a124b8f5f 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1101,7 +1101,7 @@ class Config: plugin_info = self.pluginmanager.list_plugin_distinfo() plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info} - missing_plugins = [] + missing_plugins = ["a"] for required_plugin in required_plugins: spec = None try: From 320625527a1372395f1117e635278050532cbbfe Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 13 Jun 2020 11:22:18 -0400 Subject: [PATCH 4/4] Add more tests and docs --- changelog/7346.feature.rst | 1 + doc/en/reference.rst | 4 +++- src/_pytest/config/__init__.py | 2 +- testing/test_config.py | 18 +++++++++--------- 4 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 changelog/7346.feature.rst diff --git a/changelog/7346.feature.rst b/changelog/7346.feature.rst new file mode 100644 index 000000000..fef0bbb78 --- /dev/null +++ b/changelog/7346.feature.rst @@ -0,0 +1 @@ +Version information as defined by `PEP 440 `_ may now be included when providing plugins to the ``required_plugins`` configuration option. diff --git a/doc/en/reference.rst b/doc/en/reference.rst index bf3d1fbbb..d5580ad65 100644 --- a/doc/en/reference.rst +++ b/doc/en/reference.rst @@ -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 diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index a124b8f5f..116383a73 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1101,7 +1101,7 @@ class Config: plugin_info = self.pluginmanager.list_plugin_distinfo() plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info} - missing_plugins = ["a"] + missing_plugins = [] for required_plugin in required_plugins: spec = None try: diff --git a/testing/test_config.py b/testing/test_config.py index f8c1c879e..d59d641f6 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -265,6 +265,13 @@ class TestParseIni: ( """ [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 """, @@ -280,16 +287,9 @@ class TestParseIni: ( """ [pytest] - required_plugins = pytest-xdist==aegsrgrsgs + required_plugins = pytest-xdist==aegsrgrsgs pytest-xdist==-1 pytest-xdist>2.1.1,>3.0.0 """, - "Missing required plugins: pytest-xdist==aegsrgrsgs", - ), - ( - """ - [pytest] - required_plugins = pytest-xdist==-1 - """, - "Missing required plugins: pytest-xdist==-1", + "Missing required plugins: pytest-xdist==-1, pytest-xdist==aegsrgrsgs, pytest-xdist>2.1.1,>3.0.0", ), ( """