From 8c734dfc2f98e617ca7796ab0af74abdb747a34c Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 27 Mar 2019 19:10:33 +0100 Subject: [PATCH] Split out list of essential plugins Fixes https://github.com/pytest-dev/pytest/issues/4976. --- src/_pytest/config/__init__.py | 14 ++++++++++---- src/_pytest/terminal.py | 1 + testing/test_config.py | 24 +++++++++--------------- testing/test_pluginmanager.py | 4 ++++ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 4ed9deac4..4542f06ab 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -112,13 +112,18 @@ def directory_arg(path, optname): return path -default_plugins = ( +# Plugins that cannot be disabled via "-p no:X" currently. +essential_plugins = ( "mark", "main", - "terminal", "runner", "python", "fixtures", + "helpconfig", # Provides -p. +) + +default_plugins = essential_plugins + ( + "terminal", # Has essential options, but xdist uses -pno:terminal. "debugging", "unittest", "capture", @@ -127,7 +132,6 @@ default_plugins = ( "monkeypatch", "recwarn", "pastebin", - "helpconfig", "nose", "assertion", "junitxml", @@ -143,7 +147,6 @@ default_plugins = ( "reports", ) - builtin_plugins = set(default_plugins) builtin_plugins.add("pytester") @@ -496,6 +499,9 @@ class PytestPluginManager(PluginManager): def consider_pluginarg(self, arg): if arg.startswith("no:"): name = arg[3:] + if name in essential_plugins: + raise UsageError("plugin %s cannot be disabled" % name) + # PR #4304 : remove stepwise if cacheprovider is blocked if name == "cacheprovider": self.set_blocked("stepwise") diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 06604fdf1..31c0da46d 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -173,6 +173,7 @@ def getreportopt(config): return reportopts +@pytest.hookimpl(trylast=True) # after _pytest.runner def pytest_report_teststatus(report): if report.passed: letter = "." diff --git a/testing/test_config.py b/testing/test_config.py index c90333a00..8cd606f45 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1205,20 +1205,12 @@ def test_config_does_not_load_blocked_plugin_from_args(testdir): [ x for x in _pytest.config.default_plugins - if x - not in [ - "fixtures", - "helpconfig", # Provides -p. - "main", - "mark", - "python", - "runner", - "terminal", # works in OK case (no output), but not with failures. - ] + if x not in _pytest.config.essential_plugins ], ) def test_config_blocked_default_plugins(testdir, plugin): if plugin == "debugging": + # Fixed in xdist master (after 1.27.0). # https://github.com/pytest-dev/pytest-xdist/pull/422 try: import xdist # noqa: F401 @@ -1230,9 +1222,11 @@ def test_config_blocked_default_plugins(testdir, plugin): p = testdir.makepyfile("def test(): pass") result = testdir.runpytest(str(p), "-pno:%s" % plugin) assert result.ret == EXIT_OK - result.stdout.fnmatch_lines(["* 1 passed in *"]) + if plugin != "terminal": + result.stdout.fnmatch_lines(["* 1 passed in *"]) - p = testdir.makepyfile("def test(): assert 0") - result = testdir.runpytest(str(p), "-pno:%s" % plugin) - assert result.ret == EXIT_TESTSFAILED - result.stdout.fnmatch_lines(["* 1 failed in *"]) + if plugin != "terminal": # fails to report due to its options being used elsewhere. + p = testdir.makepyfile("def test(): assert 0") + result = testdir.runpytest(str(p), "-pno:%s" % plugin) + assert result.ret == EXIT_TESTSFAILED + result.stdout.fnmatch_lines(["* 1 failed in *"]) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 614572ae4..12990c867 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -9,6 +9,7 @@ import types import pytest from _pytest.config import PytestPluginManager +from _pytest.config.exceptions import UsageError from _pytest.main import EXIT_NOTESTSCOLLECTED from _pytest.main import Session @@ -314,6 +315,9 @@ class TestPytestPluginManagerBootstrapming(object): # Handles -p without following arg (when used without argparse). pytestpm.consider_preparse(["-p"]) + with pytest.raises(UsageError, match="^plugin main cannot be disabled$"): + pytestpm.consider_preparse(["-p", "no:main"]) + def test_plugin_prevent_register(self, pytestpm): pytestpm.consider_preparse(["xyz", "-p", "no:abc"]) l1 = pytestpm.get_plugins()