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.
|
||||
Thanks Holger Krekel.
|
||||
|
||||
- pluginmanagement: introduce ``pytest.hookimpl_opts`` and
|
||||
``pytest.hookspec_opts`` decorators for setting impl/spec
|
||||
- pluginmanagement: introduce ``pytest.hookimpl`` and
|
||||
``pytest.hookspec`` decorators for setting impl/spec
|
||||
specific parameters. This substitutes the previous
|
||||
now deprecated use of ``pytest.mark`` which is meant to
|
||||
contain markers for test functions only.
|
||||
|
|
|
@ -29,7 +29,7 @@ def pytest_addoption(parser):
|
|||
help="shortcut for --capture=no.")
|
||||
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_load_initial_conftests(early_config, parser, args):
|
||||
ns = early_config.known_args_namespace
|
||||
pluginmanager = early_config.pluginmanager
|
||||
|
@ -101,7 +101,7 @@ class CaptureManager:
|
|||
if capfuncarg is not None:
|
||||
capfuncarg.close()
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_make_collect_report(self, collector):
|
||||
if isinstance(collector, pytest.File):
|
||||
self.resumecapture()
|
||||
|
@ -115,13 +115,13 @@ class CaptureManager:
|
|||
else:
|
||||
yield
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_setup(self, item):
|
||||
self.resumecapture()
|
||||
yield
|
||||
self.suspendcapture_item(item, "setup")
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_call(self, item):
|
||||
self.resumecapture()
|
||||
self.activate_funcargs(item)
|
||||
|
@ -129,17 +129,17 @@ class CaptureManager:
|
|||
#self.deactivate_funcargs() called from suspendcapture()
|
||||
self.suspendcapture_item(item, "call")
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_teardown(self, item):
|
||||
self.resumecapture()
|
||||
yield
|
||||
self.suspendcapture_item(item, "teardown")
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_keyboard_interrupt(self, excinfo):
|
||||
self.reset_capturings()
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_internalerror(self, excinfo):
|
||||
self.reset_capturings()
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import warnings
|
|||
import py
|
||||
# DON't import pytest here because it causes import cycle troubles
|
||||
import sys, os
|
||||
from _pytest import hookspec # the extension point definitions
|
||||
from pluggy import PluginManager, HookimplDecorator, HookspecDecorator
|
||||
import _pytest.hookspec # the extension point definitions
|
||||
from pluggy import PluginManager, HookimplMarker, HookspecMarker
|
||||
|
||||
hookimpl_opts = HookimplDecorator("pytest")
|
||||
hookspec_opts = HookspecDecorator("pytest")
|
||||
hookimpl = HookimplMarker("pytest")
|
||||
hookspec = HookspecMarker("pytest")
|
||||
|
||||
# pytest startup
|
||||
#
|
||||
|
@ -121,7 +121,7 @@ class PytestPluginManager(PluginManager):
|
|||
self._conftestpath2mod = {}
|
||||
self._confcutdir = None
|
||||
|
||||
self.add_hookspecs(hookspec)
|
||||
self.add_hookspecs(_pytest.hookspec)
|
||||
self.register(self)
|
||||
if os.environ.get('PYTEST_DEBUG'):
|
||||
err = sys.stderr
|
||||
|
@ -184,7 +184,7 @@ class PytestPluginManager(PluginManager):
|
|||
return self.get_plugin(name)
|
||||
|
||||
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
|
||||
config.addinivalue_line("markers",
|
||||
"tryfirst: mark a hook implementation function such that the "
|
||||
|
@ -827,7 +827,7 @@ class Config(object):
|
|||
if not hasattr(self.option, opt.dest):
|
||||
setattr(self.option, opt.dest, opt.default)
|
||||
|
||||
@hookimpl_opts(trylast=True)
|
||||
@hookimpl(trylast=True)
|
||||
def pytest_load_initial_conftests(self, early_config):
|
||||
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'.")
|
||||
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_cmdline_parse():
|
||||
outcome = yield
|
||||
config = outcome.get_result()
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
""" 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
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(historic=True)
|
||||
@hookspec(historic=True)
|
||||
def pytest_addhooks(pluginmanager):
|
||||
"""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():
|
||||
"""return dict of name->object to be made globally available in
|
||||
the pytest namespace. This hook is called at plugin registration
|
||||
time.
|
||||
"""
|
||||
|
||||
@hookspec_opts(historic=True)
|
||||
@hookspec(historic=True)
|
||||
def pytest_plugin_registered(plugin, manager):
|
||||
""" a new pytest plugin got registered. """
|
||||
|
||||
|
||||
@hookspec_opts(historic=True)
|
||||
@hookspec(historic=True)
|
||||
def pytest_addoption(parser):
|
||||
"""register argparse-style options and ini-style config values.
|
||||
|
||||
|
@ -52,7 +52,7 @@ def pytest_addoption(parser):
|
|||
via (deprecated) ``pytest.config``.
|
||||
"""
|
||||
|
||||
@hookspec_opts(historic=True)
|
||||
@hookspec(historic=True)
|
||||
def pytest_configure(config):
|
||||
""" called after command line options have been parsed
|
||||
and all plugins and initial conftest files been loaded.
|
||||
|
@ -65,14 +65,14 @@ def pytest_configure(config):
|
|||
# discoverable conftest.py local plugins.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_cmdline_parse(pluginmanager, args):
|
||||
"""return initialized config object, parsing the specified args. """
|
||||
|
||||
def pytest_cmdline_preparse(config, args):
|
||||
"""(deprecated) modify command line arguments before option parsing. """
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_cmdline_main(config):
|
||||
""" called for performing the main command line action. The default
|
||||
implementation will invoke the configure hooks and runtest_mainloop. """
|
||||
|
@ -86,7 +86,7 @@ def pytest_load_initial_conftests(args, early_config, parser):
|
|||
# collection hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_collection(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):
|
||||
""" called after collection has been performed and modified. """
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_ignore_collect(path, config):
|
||||
""" return True to prevent considering this path for collection.
|
||||
This hook is consulted for all files and directories prior to calling
|
||||
more specific hooks.
|
||||
"""
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_collect_directory(path, parent):
|
||||
""" called before traversing a directory for collection files. """
|
||||
|
||||
|
@ -125,7 +125,7 @@ def pytest_collectreport(report):
|
|||
def pytest_deselected(items):
|
||||
""" called for test items deselected by keyword. """
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_make_collect_report(collector):
|
||||
""" perform ``collector.collect()`` and return a CollectReport. """
|
||||
|
||||
|
@ -133,7 +133,7 @@ def pytest_make_collect_report(collector):
|
|||
# Python test function related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
""" return a Module collector or None for the given 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.
|
||||
"""
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
""" 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):
|
||||
""" call underlying test function. """
|
||||
|
||||
|
@ -156,7 +156,7 @@ def pytest_generate_tests(metafunc):
|
|||
# generic runtest related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtestloop(session):
|
||||
""" called for performing the main runtest loop
|
||||
(after collection finished). """
|
||||
|
@ -164,7 +164,7 @@ def pytest_runtestloop(session):
|
|||
def pytest_itemstart(item, node):
|
||||
""" (deprecated, use pytest_runtest_logstart). """
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
""" implements the runtest_setup/call/teardown protocol for
|
||||
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.
|
||||
"""
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
""" return a :py:class:`_pytest.runner.TestReport` object
|
||||
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):
|
||||
""" return a string to be displayed as header info for terminal reporting."""
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_report_teststatus(report):
|
||||
""" return result-category, shortletter and verbose word for reporting."""
|
||||
|
||||
|
@ -258,7 +258,7 @@ def pytest_logwarning(message, code, nodeid, fslocation):
|
|||
# doctest hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@hookspec_opts(firstresult=True)
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_doctest_prepare_content(content):
|
||||
""" return processed content for a given doctest"""
|
||||
|
||||
|
|
|
@ -512,12 +512,12 @@ class Session(FSCollector):
|
|||
def _makeid(self):
|
||||
return ""
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_collectstart(self):
|
||||
if self.shouldstop:
|
||||
raise self.Interrupted(self.shouldstop)
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_logreport(self, report):
|
||||
if report.failed and not hasattr(report, 'wasxfail'):
|
||||
self._testsfailed += 1
|
||||
|
|
|
@ -24,7 +24,7 @@ def pytest_runtest_makereport(item, call):
|
|||
call.excinfo = call2.excinfo
|
||||
|
||||
|
||||
@pytest.hookimpl_opts(trylast=True)
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_runtest_setup(item):
|
||||
if is_potential_nosetest(item):
|
||||
if isinstance(item.parent, pytest.Generator):
|
||||
|
|
|
@ -11,7 +11,7 @@ def pytest_addoption(parser):
|
|||
choices=['failed', 'all'],
|
||||
help="send failed|all info to bpaste.net pastebin service.")
|
||||
|
||||
@pytest.hookimpl_opts(trylast=True)
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_configure(config):
|
||||
if config.option.pastebin == "all":
|
||||
tr = config.pluginmanager.getplugin('terminalreporter')
|
||||
|
|
|
@ -80,7 +80,7 @@ class LsofFdLeakChecker(object):
|
|||
else:
|
||||
return True
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True, tryfirst=True)
|
||||
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
|
||||
def pytest_runtest_item(self, item):
|
||||
lines1 = self.get_open_files()
|
||||
yield
|
||||
|
|
|
@ -181,7 +181,7 @@ def pytest_configure(config):
|
|||
def pytest_sessionstart(session):
|
||||
session._fixturemanager = FixtureManager(session)
|
||||
|
||||
@pytest.hookimpl_opts(trylast=True)
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_namespace():
|
||||
raises.Exception = pytest.fail.Exception
|
||||
return {
|
||||
|
@ -200,7 +200,7 @@ def pytestconfig(request):
|
|||
return request.config
|
||||
|
||||
|
||||
@pytest.hookimpl_opts(trylast=True)
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
testfunction = pyfuncitem.obj
|
||||
if pyfuncitem._isyieldedfunction():
|
||||
|
@ -228,7 +228,7 @@ def pytest_collect_file(path, parent):
|
|||
def pytest_pycollect_makemodule(path, parent):
|
||||
return Module(path, parent)
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
outcome = yield
|
||||
res = outcome.get_result()
|
||||
|
|
|
@ -133,7 +133,7 @@ class MarkEvaluator:
|
|||
return expl
|
||||
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_setup(item):
|
||||
evalskip = MarkEvaluator(item, 'skipif')
|
||||
if evalskip.istrue():
|
||||
|
@ -151,7 +151,7 @@ def check_xfail_no_run(item):
|
|||
if not evalxfail.get('run', True):
|
||||
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
|
|
|
@ -268,7 +268,7 @@ class TerminalReporter:
|
|||
def pytest_collection_modifyitems(self):
|
||||
self.report_collect(True)
|
||||
|
||||
@pytest.hookimpl_opts(trylast=True)
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_sessionstart(self, session):
|
||||
self._sessionstarttime = time.time()
|
||||
if not self.showheader:
|
||||
|
@ -355,7 +355,7 @@ class TerminalReporter:
|
|||
indent = (len(stack) - 1) * " "
|
||||
self._tw.line("%s%s" % (indent, col))
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_sessionfinish(self, exitstatus):
|
||||
outcome = yield
|
||||
outcome.get_result()
|
||||
|
|
|
@ -140,7 +140,7 @@ class TestCaseFunction(pytest.Function):
|
|||
if traceback:
|
||||
excinfo.traceback = traceback
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
if isinstance(item, TestCaseFunction):
|
||||
if item._excinfo:
|
||||
|
@ -152,7 +152,7 @@ def pytest_runtest_makereport(item, call):
|
|||
|
||||
# twisted trial support
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_protocol(item):
|
||||
if isinstance(item, TestCaseFunction) and \
|
||||
'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.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
|
||||
|
@ -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.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
|
||||
|
|
|
@ -534,7 +534,7 @@ case we just write some informations out to a ``failures`` file::
|
|||
import pytest
|
||||
import os.path
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call, __multicall__):
|
||||
# execute all other hooks to obtain the report object
|
||||
rep = __multicall__.execute()
|
||||
|
@ -607,7 +607,7 @@ here is a little example implemented via a local plugin::
|
|||
|
||||
import pytest
|
||||
|
||||
@pytest.hookimpl_opts(tryfirst=True)
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call, __multicall__):
|
||||
# execute all other hooks to obtain the report object
|
||||
rep = __multicall__.execute()
|
||||
|
|
|
@ -292,7 +292,7 @@ Here is an example definition of a hook wrapper::
|
|||
|
||||
import pytest
|
||||
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
# 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
|
||||
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
|
||||
that result, however.
|
||||
|
||||
that result but it's probably better to avoid it.
|
||||
|
||||
|
||||
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:
|
||||
|
||||
1. Plugin3's pytest_collection_modifyitems called until the yield point
|
||||
2. Plugin1's pytest_collection_modifyitems is called
|
||||
3. Plugin2's pytest_collection_modifyitems is called
|
||||
4. Plugin3's pytest_collection_modifyitems called for executing after the yield
|
||||
The yield receives a :py:class:`CallOutcome` instance which encapsulates
|
||||
the result from calling the non-wrappers. Wrappers cannot modify the result.
|
||||
because it is a hook wrapper.
|
||||
|
||||
2. Plugin1's pytest_collection_modifyitems is called because it is marked
|
||||
with ``tryfirst=True``.
|
||||
|
||||
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
|
||||
``hookwrapper=True`` in which case it will influence the ordering of hookwrappers
|
||||
among each other.
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
depending on which plugins are installed.
|
||||
|
||||
|
||||
.. _`well specified hooks`:
|
||||
|
||||
.. currentmodule:: _pytest.hookspec
|
||||
|
|
|
@ -13,7 +13,7 @@ if __name__ == '__main__': # if run as a script or by 'python -m pytest'
|
|||
|
||||
from _pytest.config import (
|
||||
main, UsageError, _preloadplugins, cmdline,
|
||||
hookspec_opts, hookimpl_opts
|
||||
hookspec, hookimpl
|
||||
)
|
||||
from _pytest import __version__
|
||||
|
||||
|
|
|
@ -559,7 +559,7 @@ class TestConftestCustomization:
|
|||
b = testdir.mkdir("a").mkdir("b")
|
||||
b.join("conftest.py").write(py.code.Source("""
|
||||
import pytest
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_pycollect_makeitem():
|
||||
outcome = yield
|
||||
if outcome.excinfo is None:
|
||||
|
|
|
@ -38,7 +38,7 @@ def test_hookvalidation_unknown(testdir):
|
|||
def test_hookvalidation_optional(testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
@pytest.hookimpl_opts(optionalhook=True)
|
||||
@pytest.hookimpl(optionalhook=True)
|
||||
def pytest_hello(xyz):
|
||||
pass
|
||||
""")
|
||||
|
|
|
@ -510,7 +510,7 @@ class TestKeywordSelection:
|
|||
""")
|
||||
testdir.makepyfile(conftest="""
|
||||
import pytest
|
||||
@pytest.hookimpl_opts(hookwrapper=True)
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_pycollect_makeitem(name):
|
||||
outcome = yield
|
||||
if name == "TestClass":
|
||||
|
|
Loading…
Reference in New Issue