Introduce Config.invocation_args and Config.invocation_plugins

These attributes can be used to access the unchanged arguments passed
to pytest.main().

The intention is to use these attributes to initialize workers in
the same manner as the master node is initialized in pytest-xdist.
This commit is contained in:
Bruno Oliveira 2019-07-05 19:38:16 -03:00
parent 60a358fa2d
commit 3e669a262a
3 changed files with 45 additions and 6 deletions

View File

@ -0,0 +1,3 @@
New ``Config.invocation_args`` and ``Config.invocation_plugins`` attributes.
These attributes can be used by plugins to access the unchanged arguments passed to ``pytest.main()``.

View File

@ -70,6 +70,8 @@ def main(args=None, plugins=None):
tw.line(line.rstrip(), red=True)
return 4
else:
config.invocation_args = args
config.invocation_plugins = plugins
try:
return config.hook.pytest_cmdline_main(config=config)
finally:
@ -608,20 +610,33 @@ def _iter_rewritable_modules(package_files):
class Config:
""" access to configuration values, pluginmanager and plugin hooks. """
"""
Access to configuration values, pluginmanager and plugin hooks.
:ivar PytestPluginManager pluginmanager: the plugin manager handles plugin registration and hook invocation.
:ivar argparse.Namespace option: access to command line option as attributes.
:ivar invocation_args: list of command-line arguments as passed to pytest.main()
:ivar invocation_plugins: list of extra plugins passed to pytest.main(), might be None
:ivar py.path.local invocation_dir: directory where pytest.main() was invoked from
"""
def __init__(self, pluginmanager):
#: access to command line option as attributes.
#: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
self.option = argparse.Namespace()
from .argparsing import Parser, FILE_OR_DIR
self.option = argparse.Namespace()
self.invocation_args = None
self.invocation_plugins = None
self.invocation_dir = py.path.local()
_a = FILE_OR_DIR
self._parser = Parser(
usage="%(prog)s [options] [{}] [{}] [...]".format(_a, _a),
processopt=self._processopt,
)
#: a pluginmanager instance
self.pluginmanager = pluginmanager
self.trace = self.pluginmanager.trace.root.get("config")
self.hook = self.pluginmanager.hook
@ -631,7 +646,6 @@ class Config:
self._cleanup = []
self.pluginmanager.register(self, "pytestconfig")
self._configured = False
self.invocation_dir = py.path.local()
self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
def add_cleanup(self, func):

View File

@ -1198,6 +1198,28 @@ def test_config_does_not_load_blocked_plugin_from_args(testdir):
assert result.ret == ExitCode.USAGE_ERROR
def test_invocation_arguments(testdir):
"""Ensure that Config.invocation_* arguments are correctly defined"""
class DummyPlugin:
pass
p = testdir.makepyfile("def test(): pass")
plugin = DummyPlugin()
rec = testdir.inline_run(p, "-v", plugins=[plugin])
calls = rec.getcalls("pytest_runtest_protocol")
assert len(calls) == 1
call = calls[0]
config = call.item.config
assert config.invocation_args == [p, "-v"]
plugins = config.invocation_plugins
assert len(plugins) == 2
assert plugins[0] is plugin
assert type(plugins[1]).__name__ == "Collect" # installed by testdir.inline_run()
@pytest.mark.parametrize(
"plugin",
[