Skip to content
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 AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ Tzu-ping Chung
Vasily Kuznetsov
Victor Uriarte
Vidar T. Fauske
Virgil Dupras
Vitaly Lashmanov
Vlad Dragos
Wil Cooley
Expand Down
1 change: 1 addition & 0 deletions changelog/3784.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add option to disable plugin auto-loading.
5 changes: 5 additions & 0 deletions doc/en/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,11 @@ Contains comma-separated list of modules that should be loaded as plugins:

export PYTEST_PLUGINS=mymodule.plugin,xdist

PYTEST_DISABLE_PLUGIN_AUTOLOAD
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When set, disables plugin auto-loading through setuptools entrypoints. Only explicitly specified plugins will be
loaded.

PYTEST_CURRENT_TEST
~~~~~~~~~~~~~~~~~~~
Expand Down
9 changes: 8 additions & 1 deletion src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ def _mark_plugins_for_rewrite(self, hook):

self.pluginmanager.rewrite_hook = hook

if os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"):
# We don't autoload from setuptools entry points, no need to continue.
return

# 'RECORD' available for plugins installed normally (pip install)
# 'SOURCES.txt' available for plugins installed in dev mode (pip install -e)
# for installed plugins 'SOURCES.txt' returns an empty list, and vice-versa
Expand All @@ -726,7 +730,10 @@ def _preparse(self, args, addopts=True):
self._checkversion()
self._consider_importhook(args)
self.pluginmanager.consider_preparse(args)
self.pluginmanager.load_setuptools_entrypoints("pytest11")
if not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"):
# Don't autoload from setuptools entry point. Only explicitly specified
# plugins are going to be loaded.
self.pluginmanager.load_setuptools_entrypoints("pytest11")
self.pluginmanager.consider_env()
self.known_args_namespace = ns = self._parser.parse_known_args(
args, namespace=copy.copy(self.option)
Expand Down
1 change: 1 addition & 0 deletions src/_pytest/helpconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def showhelp(config):
vars = [
("PYTEST_ADDOPTS", "extra command line options"),
("PYTEST_PLUGINS", "comma-separated plugins to load during startup"),
("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "set to disable plugin auto-loading"),
("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals"),
]
for name, help in vars:
Expand Down
20 changes: 20 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,26 @@ def load(self):
)


@pytest.mark.parametrize(
"parse_args,should_load", [(("-p", "mytestplugin"), True), ((), False)]
)
def test_disable_plugin_autoload(testdir, monkeypatch, parse_args, should_load):
pkg_resources = pytest.importorskip("pkg_resources")

def my_iter(name):
raise AssertionError("Should not be called")

class PseudoPlugin(object):
x = 42

monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
monkeypatch.setattr(pkg_resources, "iter_entry_points", my_iter)
monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin())
config = testdir.parseconfig(*parse_args)
has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None
assert has_loaded == should_load


def test_cmdline_processargs_simple(testdir):
testdir.makeconftest(
"""
Expand Down