adapt to pluggy naming, rename pytest.hookspec_opts to pytest.hookspec,s ame with hookimpl_opts
--HG-- branch : pluggy1
This commit is contained in:
parent
5ea7f0342b
commit
bddc88f09e
|
@ -27,8 +27,8 @@
|
||||||
details like especially the pluginmanager.add_shutdown() API.
|
details like especially the pluginmanager.add_shutdown() API.
|
||||||
Thanks Holger Krekel.
|
Thanks Holger Krekel.
|
||||||
|
|
||||||
- pluginmanagement: introduce ``pytest.hookimpl_opts`` and
|
- pluginmanagement: introduce ``pytest.hookimpl`` and
|
||||||
``pytest.hookspec_opts`` decorators for setting impl/spec
|
``pytest.hookspec`` decorators for setting impl/spec
|
||||||
specific parameters. This substitutes the previous
|
specific parameters. This substitutes the previous
|
||||||
now deprecated use of ``pytest.mark`` which is meant to
|
now deprecated use of ``pytest.mark`` which is meant to
|
||||||
contain markers for test functions only.
|
contain markers for test functions only.
|
||||||
|
|
|
@ -29,7 +29,7 @@ def pytest_addoption(parser):
|
||||||
help="shortcut for --capture=no.")
|
help="shortcut for --capture=no.")
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_load_initial_conftests(early_config, parser, args):
|
def pytest_load_initial_conftests(early_config, parser, args):
|
||||||
ns = early_config.known_args_namespace
|
ns = early_config.known_args_namespace
|
||||||
pluginmanager = early_config.pluginmanager
|
pluginmanager = early_config.pluginmanager
|
||||||
|
@ -101,7 +101,7 @@ class CaptureManager:
|
||||||
if capfuncarg is not None:
|
if capfuncarg is not None:
|
||||||
capfuncarg.close()
|
capfuncarg.close()
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_make_collect_report(self, collector):
|
def pytest_make_collect_report(self, collector):
|
||||||
if isinstance(collector, pytest.File):
|
if isinstance(collector, pytest.File):
|
||||||
self.resumecapture()
|
self.resumecapture()
|
||||||
|
@ -115,13 +115,13 @@ class CaptureManager:
|
||||||
else:
|
else:
|
||||||
yield
|
yield
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_setup(self, item):
|
def pytest_runtest_setup(self, item):
|
||||||
self.resumecapture()
|
self.resumecapture()
|
||||||
yield
|
yield
|
||||||
self.suspendcapture_item(item, "setup")
|
self.suspendcapture_item(item, "setup")
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_call(self, item):
|
def pytest_runtest_call(self, item):
|
||||||
self.resumecapture()
|
self.resumecapture()
|
||||||
self.activate_funcargs(item)
|
self.activate_funcargs(item)
|
||||||
|
@ -129,17 +129,17 @@ class CaptureManager:
|
||||||
#self.deactivate_funcargs() called from suspendcapture()
|
#self.deactivate_funcargs() called from suspendcapture()
|
||||||
self.suspendcapture_item(item, "call")
|
self.suspendcapture_item(item, "call")
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_teardown(self, item):
|
def pytest_runtest_teardown(self, item):
|
||||||
self.resumecapture()
|
self.resumecapture()
|
||||||
yield
|
yield
|
||||||
self.suspendcapture_item(item, "teardown")
|
self.suspendcapture_item(item, "teardown")
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_keyboard_interrupt(self, excinfo):
|
def pytest_keyboard_interrupt(self, excinfo):
|
||||||
self.reset_capturings()
|
self.reset_capturings()
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_internalerror(self, excinfo):
|
def pytest_internalerror(self, excinfo):
|
||||||
self.reset_capturings()
|
self.reset_capturings()
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@ import warnings
|
||||||
import py
|
import py
|
||||||
# DON't import pytest here because it causes import cycle troubles
|
# DON't import pytest here because it causes import cycle troubles
|
||||||
import sys, os
|
import sys, os
|
||||||
from _pytest import hookspec # the extension point definitions
|
import _pytest.hookspec # the extension point definitions
|
||||||
from pluggy import PluginManager, HookimplDecorator, HookspecDecorator
|
from pluggy import PluginManager, HookimplMarker, HookspecMarker
|
||||||
|
|
||||||
hookimpl_opts = HookimplDecorator("pytest")
|
hookimpl = HookimplMarker("pytest")
|
||||||
hookspec_opts = HookspecDecorator("pytest")
|
hookspec = HookspecMarker("pytest")
|
||||||
|
|
||||||
# pytest startup
|
# pytest startup
|
||||||
#
|
#
|
||||||
|
@ -121,7 +121,7 @@ class PytestPluginManager(PluginManager):
|
||||||
self._conftestpath2mod = {}
|
self._conftestpath2mod = {}
|
||||||
self._confcutdir = None
|
self._confcutdir = None
|
||||||
|
|
||||||
self.add_hookspecs(hookspec)
|
self.add_hookspecs(_pytest.hookspec)
|
||||||
self.register(self)
|
self.register(self)
|
||||||
if os.environ.get('PYTEST_DEBUG'):
|
if os.environ.get('PYTEST_DEBUG'):
|
||||||
err = sys.stderr
|
err = sys.stderr
|
||||||
|
@ -184,7 +184,7 @@ class PytestPluginManager(PluginManager):
|
||||||
return self.get_plugin(name)
|
return self.get_plugin(name)
|
||||||
|
|
||||||
def pytest_configure(self, config):
|
def pytest_configure(self, config):
|
||||||
# XXX now that the pluginmanager exposes hookimpl_opts(tryfirst...)
|
# XXX now that the pluginmanager exposes hookimpl(tryfirst...)
|
||||||
# we should remove tryfirst/trylast as markers
|
# we should remove tryfirst/trylast as markers
|
||||||
config.addinivalue_line("markers",
|
config.addinivalue_line("markers",
|
||||||
"tryfirst: mark a hook implementation function such that the "
|
"tryfirst: mark a hook implementation function such that the "
|
||||||
|
@ -827,7 +827,7 @@ class Config(object):
|
||||||
if not hasattr(self.option, opt.dest):
|
if not hasattr(self.option, opt.dest):
|
||||||
setattr(self.option, opt.dest, opt.default)
|
setattr(self.option, opt.dest, opt.default)
|
||||||
|
|
||||||
@hookimpl_opts(trylast=True)
|
@hookimpl(trylast=True)
|
||||||
def pytest_load_initial_conftests(self, early_config):
|
def pytest_load_initial_conftests(self, early_config):
|
||||||
self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
|
self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ def pytest_addoption(parser):
|
||||||
help="store internal tracing debug information in 'pytestdebug.log'.")
|
help="store internal tracing debug information in 'pytestdebug.log'.")
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_cmdline_parse():
|
def pytest_cmdline_parse():
|
||||||
outcome = yield
|
outcome = yield
|
||||||
config = outcome.get_result()
|
config = outcome.get_result()
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
|
""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
|
||||||
|
|
||||||
from pluggy import HookspecDecorator
|
from pluggy import HookspecMarker
|
||||||
|
|
||||||
hookspec_opts = HookspecDecorator("pytest")
|
hookspec = HookspecMarker("pytest")
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Initialization hooks called for every plugin
|
# Initialization hooks called for every plugin
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(historic=True)
|
@hookspec(historic=True)
|
||||||
def pytest_addhooks(pluginmanager):
|
def pytest_addhooks(pluginmanager):
|
||||||
"""called at plugin registration time to allow adding new hooks via a call to
|
"""called at plugin registration time to allow adding new hooks via a call to
|
||||||
pluginmanager.addhooks(module_or_class, prefix)."""
|
pluginmanager.add_hookspecs(module_or_class, prefix)."""
|
||||||
|
|
||||||
|
|
||||||
@hookspec_opts(historic=True)
|
@hookspec(historic=True)
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
"""return dict of name->object to be made globally available in
|
"""return dict of name->object to be made globally available in
|
||||||
the pytest namespace. This hook is called at plugin registration
|
the pytest namespace. This hook is called at plugin registration
|
||||||
time.
|
time.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@hookspec_opts(historic=True)
|
@hookspec(historic=True)
|
||||||
def pytest_plugin_registered(plugin, manager):
|
def pytest_plugin_registered(plugin, manager):
|
||||||
""" a new pytest plugin got registered. """
|
""" a new pytest plugin got registered. """
|
||||||
|
|
||||||
|
|
||||||
@hookspec_opts(historic=True)
|
@hookspec(historic=True)
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
"""register argparse-style options and ini-style config values.
|
"""register argparse-style options and ini-style config values.
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ def pytest_addoption(parser):
|
||||||
via (deprecated) ``pytest.config``.
|
via (deprecated) ``pytest.config``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@hookspec_opts(historic=True)
|
@hookspec(historic=True)
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
""" called after command line options have been parsed
|
""" called after command line options have been parsed
|
||||||
and all plugins and initial conftest files been loaded.
|
and all plugins and initial conftest files been loaded.
|
||||||
|
@ -65,14 +65,14 @@ def pytest_configure(config):
|
||||||
# discoverable conftest.py local plugins.
|
# discoverable conftest.py local plugins.
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_cmdline_parse(pluginmanager, args):
|
def pytest_cmdline_parse(pluginmanager, args):
|
||||||
"""return initialized config object, parsing the specified args. """
|
"""return initialized config object, parsing the specified args. """
|
||||||
|
|
||||||
def pytest_cmdline_preparse(config, args):
|
def pytest_cmdline_preparse(config, args):
|
||||||
"""(deprecated) modify command line arguments before option parsing. """
|
"""(deprecated) modify command line arguments before option parsing. """
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_cmdline_main(config):
|
def pytest_cmdline_main(config):
|
||||||
""" called for performing the main command line action. The default
|
""" called for performing the main command line action. The default
|
||||||
implementation will invoke the configure hooks and runtest_mainloop. """
|
implementation will invoke the configure hooks and runtest_mainloop. """
|
||||||
|
@ -86,7 +86,7 @@ def pytest_load_initial_conftests(args, early_config, parser):
|
||||||
# collection hooks
|
# collection hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_collection(session):
|
def pytest_collection(session):
|
||||||
""" perform the collection protocol for the given session. """
|
""" perform the collection protocol for the given session. """
|
||||||
|
|
||||||
|
@ -97,14 +97,14 @@ def pytest_collection_modifyitems(session, config, items):
|
||||||
def pytest_collection_finish(session):
|
def pytest_collection_finish(session):
|
||||||
""" called after collection has been performed and modified. """
|
""" called after collection has been performed and modified. """
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_ignore_collect(path, config):
|
def pytest_ignore_collect(path, config):
|
||||||
""" return True to prevent considering this path for collection.
|
""" return True to prevent considering this path for collection.
|
||||||
This hook is consulted for all files and directories prior to calling
|
This hook is consulted for all files and directories prior to calling
|
||||||
more specific hooks.
|
more specific hooks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_collect_directory(path, parent):
|
def pytest_collect_directory(path, parent):
|
||||||
""" called before traversing a directory for collection files. """
|
""" called before traversing a directory for collection files. """
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ def pytest_collectreport(report):
|
||||||
def pytest_deselected(items):
|
def pytest_deselected(items):
|
||||||
""" called for test items deselected by keyword. """
|
""" called for test items deselected by keyword. """
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_make_collect_report(collector):
|
def pytest_make_collect_report(collector):
|
||||||
""" perform ``collector.collect()`` and return a CollectReport. """
|
""" perform ``collector.collect()`` and return a CollectReport. """
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ def pytest_make_collect_report(collector):
|
||||||
# Python test function related hooks
|
# Python test function related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_pycollect_makemodule(path, parent):
|
def pytest_pycollect_makemodule(path, parent):
|
||||||
""" return a Module collector or None for the given path.
|
""" return a Module collector or None for the given path.
|
||||||
This hook will be called for each matching test module path.
|
This hook will be called for each matching test module path.
|
||||||
|
@ -141,11 +141,11 @@ def pytest_pycollect_makemodule(path, parent):
|
||||||
create test modules for files that do not match as a test module.
|
create test modules for files that do not match as a test module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_pycollect_makeitem(collector, name, obj):
|
def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
""" return custom item/collector for a python object in a module, or None. """
|
""" return custom item/collector for a python object in a module, or None. """
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_pyfunc_call(pyfuncitem):
|
def pytest_pyfunc_call(pyfuncitem):
|
||||||
""" call underlying test function. """
|
""" call underlying test function. """
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ def pytest_generate_tests(metafunc):
|
||||||
# generic runtest related hooks
|
# generic runtest related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_runtestloop(session):
|
def pytest_runtestloop(session):
|
||||||
""" called for performing the main runtest loop
|
""" called for performing the main runtest loop
|
||||||
(after collection finished). """
|
(after collection finished). """
|
||||||
|
@ -164,7 +164,7 @@ def pytest_runtestloop(session):
|
||||||
def pytest_itemstart(item, node):
|
def pytest_itemstart(item, node):
|
||||||
""" (deprecated, use pytest_runtest_logstart). """
|
""" (deprecated, use pytest_runtest_logstart). """
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_runtest_protocol(item, nextitem):
|
def pytest_runtest_protocol(item, nextitem):
|
||||||
""" implements the runtest_setup/call/teardown protocol for
|
""" implements the runtest_setup/call/teardown protocol for
|
||||||
the given test item, including capturing exceptions and calling
|
the given test item, including capturing exceptions and calling
|
||||||
|
@ -197,7 +197,7 @@ def pytest_runtest_teardown(item, nextitem):
|
||||||
so that nextitem only needs to call setup-functions.
|
so that nextitem only needs to call setup-functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
""" return a :py:class:`_pytest.runner.TestReport` object
|
""" return a :py:class:`_pytest.runner.TestReport` object
|
||||||
for the given :py:class:`pytest.Item` and
|
for the given :py:class:`pytest.Item` and
|
||||||
|
@ -242,7 +242,7 @@ def pytest_assertrepr_compare(config, op, left, right):
|
||||||
def pytest_report_header(config, startdir):
|
def pytest_report_header(config, startdir):
|
||||||
""" return a string to be displayed as header info for terminal reporting."""
|
""" return a string to be displayed as header info for terminal reporting."""
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_report_teststatus(report):
|
def pytest_report_teststatus(report):
|
||||||
""" return result-category, shortletter and verbose word for reporting."""
|
""" return result-category, shortletter and verbose word for reporting."""
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ def pytest_logwarning(message, code, nodeid, fslocation):
|
||||||
# doctest hooks
|
# doctest hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
@hookspec_opts(firstresult=True)
|
@hookspec(firstresult=True)
|
||||||
def pytest_doctest_prepare_content(content):
|
def pytest_doctest_prepare_content(content):
|
||||||
""" return processed content for a given doctest"""
|
""" return processed content for a given doctest"""
|
||||||
|
|
||||||
|
|
|
@ -512,12 +512,12 @@ class Session(FSCollector):
|
||||||
def _makeid(self):
|
def _makeid(self):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_collectstart(self):
|
def pytest_collectstart(self):
|
||||||
if self.shouldstop:
|
if self.shouldstop:
|
||||||
raise self.Interrupted(self.shouldstop)
|
raise self.Interrupted(self.shouldstop)
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_logreport(self, report):
|
def pytest_runtest_logreport(self, report):
|
||||||
if report.failed and not hasattr(report, 'wasxfail'):
|
if report.failed and not hasattr(report, 'wasxfail'):
|
||||||
self._testsfailed += 1
|
self._testsfailed += 1
|
||||||
|
|
|
@ -24,7 +24,7 @@ def pytest_runtest_makereport(item, call):
|
||||||
call.excinfo = call2.excinfo
|
call.excinfo = call2.excinfo
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
if is_potential_nosetest(item):
|
if is_potential_nosetest(item):
|
||||||
if isinstance(item.parent, pytest.Generator):
|
if isinstance(item.parent, pytest.Generator):
|
||||||
|
|
|
@ -11,7 +11,7 @@ def pytest_addoption(parser):
|
||||||
choices=['failed', 'all'],
|
choices=['failed', 'all'],
|
||||||
help="send failed|all info to bpaste.net pastebin service.")
|
help="send failed|all info to bpaste.net pastebin service.")
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
if config.option.pastebin == "all":
|
if config.option.pastebin == "all":
|
||||||
tr = config.pluginmanager.getplugin('terminalreporter')
|
tr = config.pluginmanager.getplugin('terminalreporter')
|
||||||
|
|
|
@ -80,7 +80,7 @@ class LsofFdLeakChecker(object):
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True, tryfirst=True)
|
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
|
||||||
def pytest_runtest_item(self, item):
|
def pytest_runtest_item(self, item):
|
||||||
lines1 = self.get_open_files()
|
lines1 = self.get_open_files()
|
||||||
yield
|
yield
|
||||||
|
|
|
@ -181,7 +181,7 @@ def pytest_configure(config):
|
||||||
def pytest_sessionstart(session):
|
def pytest_sessionstart(session):
|
||||||
session._fixturemanager = FixtureManager(session)
|
session._fixturemanager = FixtureManager(session)
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
raises.Exception = pytest.fail.Exception
|
raises.Exception = pytest.fail.Exception
|
||||||
return {
|
return {
|
||||||
|
@ -200,7 +200,7 @@ def pytestconfig(request):
|
||||||
return request.config
|
return request.config
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_pyfunc_call(pyfuncitem):
|
def pytest_pyfunc_call(pyfuncitem):
|
||||||
testfunction = pyfuncitem.obj
|
testfunction = pyfuncitem.obj
|
||||||
if pyfuncitem._isyieldedfunction():
|
if pyfuncitem._isyieldedfunction():
|
||||||
|
@ -228,7 +228,7 @@ def pytest_collect_file(path, parent):
|
||||||
def pytest_pycollect_makemodule(path, parent):
|
def pytest_pycollect_makemodule(path, parent):
|
||||||
return Module(path, parent)
|
return Module(path, parent)
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_pycollect_makeitem(collector, name, obj):
|
def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
res = outcome.get_result()
|
res = outcome.get_result()
|
||||||
|
|
|
@ -133,7 +133,7 @@ class MarkEvaluator:
|
||||||
return expl
|
return expl
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
evalskip = MarkEvaluator(item, 'skipif')
|
evalskip = MarkEvaluator(item, 'skipif')
|
||||||
if evalskip.istrue():
|
if evalskip.istrue():
|
||||||
|
@ -151,7 +151,7 @@ def check_xfail_no_run(item):
|
||||||
if not evalxfail.get('run', True):
|
if not evalxfail.get('run', True):
|
||||||
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
rep = outcome.get_result()
|
rep = outcome.get_result()
|
||||||
|
|
|
@ -268,7 +268,7 @@ class TerminalReporter:
|
||||||
def pytest_collection_modifyitems(self):
|
def pytest_collection_modifyitems(self):
|
||||||
self.report_collect(True)
|
self.report_collect(True)
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_sessionstart(self, session):
|
def pytest_sessionstart(self, session):
|
||||||
self._sessionstarttime = time.time()
|
self._sessionstarttime = time.time()
|
||||||
if not self.showheader:
|
if not self.showheader:
|
||||||
|
@ -355,7 +355,7 @@ class TerminalReporter:
|
||||||
indent = (len(stack) - 1) * " "
|
indent = (len(stack) - 1) * " "
|
||||||
self._tw.line("%s%s" % (indent, col))
|
self._tw.line("%s%s" % (indent, col))
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_sessionfinish(self, exitstatus):
|
def pytest_sessionfinish(self, exitstatus):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
outcome.get_result()
|
outcome.get_result()
|
||||||
|
|
|
@ -140,7 +140,7 @@ class TestCaseFunction(pytest.Function):
|
||||||
if traceback:
|
if traceback:
|
||||||
excinfo.traceback = traceback
|
excinfo.traceback = traceback
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
if isinstance(item, TestCaseFunction):
|
if isinstance(item, TestCaseFunction):
|
||||||
if item._excinfo:
|
if item._excinfo:
|
||||||
|
@ -152,7 +152,7 @@ def pytest_runtest_makereport(item, call):
|
||||||
|
|
||||||
# twisted trial support
|
# twisted trial support
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_protocol(item):
|
def pytest_runtest_protocol(item):
|
||||||
if isinstance(item, TestCaseFunction) and \
|
if isinstance(item, TestCaseFunction) and \
|
||||||
'twisted.trial.unittest' in sys.modules:
|
'twisted.trial.unittest' in sys.modules:
|
||||||
|
|
|
@ -201,9 +201,9 @@ You can ask which markers exist for your test suite - the list includes our just
|
||||||
|
|
||||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True): mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
@pytest.hookimpl(tryfirst=True): mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True): mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
@pytest.hookimpl(trylast=True): mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||||
|
|
||||||
|
|
||||||
For an example on how to add and work with markers from a plugin, see
|
For an example on how to add and work with markers from a plugin, see
|
||||||
|
@ -375,9 +375,9 @@ The ``--markers`` option always gives you a list of available markers::
|
||||||
|
|
||||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True): mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
@pytest.hookimpl(tryfirst=True): mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||||
|
|
||||||
@pytest.hookimpl_opts(trylast=True): mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
@pytest.hookimpl(trylast=True): mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||||
|
|
||||||
|
|
||||||
Reading markers which were set from multiple places
|
Reading markers which were set from multiple places
|
||||||
|
|
|
@ -534,7 +534,7 @@ case we just write some informations out to a ``failures`` file::
|
||||||
import pytest
|
import pytest
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_makereport(item, call, __multicall__):
|
def pytest_runtest_makereport(item, call, __multicall__):
|
||||||
# execute all other hooks to obtain the report object
|
# execute all other hooks to obtain the report object
|
||||||
rep = __multicall__.execute()
|
rep = __multicall__.execute()
|
||||||
|
@ -607,7 +607,7 @@ here is a little example implemented via a local plugin::
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.hookimpl_opts(tryfirst=True)
|
@pytest.hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_makereport(item, call, __multicall__):
|
def pytest_runtest_makereport(item, call, __multicall__):
|
||||||
# execute all other hooks to obtain the report object
|
# execute all other hooks to obtain the report object
|
||||||
rep = __multicall__.execute()
|
rep = __multicall__.execute()
|
||||||
|
|
|
@ -292,7 +292,7 @@ Here is an example definition of a hook wrapper::
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_pyfunc_call(pyfuncitem):
|
def pytest_pyfunc_call(pyfuncitem):
|
||||||
# do whatever you want before the next hook executes
|
# do whatever you want before the next hook executes
|
||||||
|
|
||||||
|
@ -305,8 +305,7 @@ Here is an example definition of a hook wrapper::
|
||||||
Note that hook wrappers don't return results themselves, they merely
|
Note that hook wrappers don't return results themselves, they merely
|
||||||
perform tracing or other side effects around the actual hook implementations.
|
perform tracing or other side effects around the actual hook implementations.
|
||||||
If the result of the underlying hook is a mutable object, they may modify
|
If the result of the underlying hook is a mutable object, they may modify
|
||||||
that result, however.
|
that result but it's probably better to avoid it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Hook function ordering / call example
|
Hook function ordering / call example
|
||||||
|
@ -338,16 +337,24 @@ after others, i.e. the position in the ``N``-sized list of functions::
|
||||||
Here is the order of execution:
|
Here is the order of execution:
|
||||||
|
|
||||||
1. Plugin3's pytest_collection_modifyitems called until the yield point
|
1. Plugin3's pytest_collection_modifyitems called until the yield point
|
||||||
2. Plugin1's pytest_collection_modifyitems is called
|
because it is a hook wrapper.
|
||||||
3. Plugin2's pytest_collection_modifyitems is called
|
|
||||||
4. Plugin3's pytest_collection_modifyitems called for executing after the yield
|
2. Plugin1's pytest_collection_modifyitems is called because it is marked
|
||||||
The yield receives a :py:class:`CallOutcome` instance which encapsulates
|
with ``tryfirst=True``.
|
||||||
the result from calling the non-wrappers. Wrappers cannot modify the result.
|
|
||||||
|
3. Plugin2's pytest_collection_modifyitems is called because it is marked
|
||||||
|
with ``trylast=True`` (but even without this mark it would come after
|
||||||
|
Plugin1).
|
||||||
|
|
||||||
|
4. Plugin3's pytest_collection_modifyitems then executing the code after the yield
|
||||||
|
point. The yield receives a :py:class:`CallOutcome` instance which encapsulates
|
||||||
|
the result from calling the non-wrappers. Wrappers shall not modify the result.
|
||||||
|
|
||||||
It's possible to use ``tryfirst`` and ``trylast`` also in conjunction with
|
It's possible to use ``tryfirst`` and ``trylast`` also in conjunction with
|
||||||
``hookwrapper=True`` in which case it will influence the ordering of hookwrappers
|
``hookwrapper=True`` in which case it will influence the ordering of hookwrappers
|
||||||
among each other.
|
among each other.
|
||||||
|
|
||||||
|
|
||||||
Declaring new hooks
|
Declaring new hooks
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -368,11 +375,11 @@ For an example, see `newhooks.py`_ from :ref:`xdist`.
|
||||||
.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default
|
.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default
|
||||||
|
|
||||||
|
|
||||||
Using hooks from 3rd party plugins
|
Optionally using hooks from 3rd party plugins
|
||||||
-------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
Using new hooks from plugins as explained above might be a little tricky
|
Using new hooks from plugins as explained above might be a little tricky
|
||||||
because the standard :ref:`validation mechanism <validation>`:
|
because of the standard :ref:`validation mechanism <validation>`:
|
||||||
if you depend on a plugin that is not installed, validation will fail and
|
if you depend on a plugin that is not installed, validation will fail and
|
||||||
the error message will not make much sense to your users.
|
the error message will not make much sense to your users.
|
||||||
|
|
||||||
|
@ -395,7 +402,6 @@ declaring the hook functions directly in your plugin module, for example::
|
||||||
This has the added benefit of allowing you to conditionally install hooks
|
This has the added benefit of allowing you to conditionally install hooks
|
||||||
depending on which plugins are installed.
|
depending on which plugins are installed.
|
||||||
|
|
||||||
|
|
||||||
.. _`well specified hooks`:
|
.. _`well specified hooks`:
|
||||||
|
|
||||||
.. currentmodule:: _pytest.hookspec
|
.. currentmodule:: _pytest.hookspec
|
||||||
|
|
|
@ -13,7 +13,7 @@ if __name__ == '__main__': # if run as a script or by 'python -m pytest'
|
||||||
|
|
||||||
from _pytest.config import (
|
from _pytest.config import (
|
||||||
main, UsageError, _preloadplugins, cmdline,
|
main, UsageError, _preloadplugins, cmdline,
|
||||||
hookspec_opts, hookimpl_opts
|
hookspec, hookimpl
|
||||||
)
|
)
|
||||||
from _pytest import __version__
|
from _pytest import __version__
|
||||||
|
|
||||||
|
|
|
@ -559,7 +559,7 @@ class TestConftestCustomization:
|
||||||
b = testdir.mkdir("a").mkdir("b")
|
b = testdir.mkdir("a").mkdir("b")
|
||||||
b.join("conftest.py").write(py.code.Source("""
|
b.join("conftest.py").write(py.code.Source("""
|
||||||
import pytest
|
import pytest
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_pycollect_makeitem():
|
def pytest_pycollect_makeitem():
|
||||||
outcome = yield
|
outcome = yield
|
||||||
if outcome.excinfo is None:
|
if outcome.excinfo is None:
|
||||||
|
|
|
@ -38,7 +38,7 @@ def test_hookvalidation_unknown(testdir):
|
||||||
def test_hookvalidation_optional(testdir):
|
def test_hookvalidation_optional(testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import pytest
|
import pytest
|
||||||
@pytest.hookimpl_opts(optionalhook=True)
|
@pytest.hookimpl(optionalhook=True)
|
||||||
def pytest_hello(xyz):
|
def pytest_hello(xyz):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -510,7 +510,7 @@ class TestKeywordSelection:
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile(conftest="""
|
testdir.makepyfile(conftest="""
|
||||||
import pytest
|
import pytest
|
||||||
@pytest.hookimpl_opts(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_pycollect_makeitem(name):
|
def pytest_pycollect_makeitem(name):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
if name == "TestClass":
|
if name == "TestClass":
|
||||||
|
|
Loading…
Reference in New Issue