Type annotate some hookspecs & impls

Annotate some "easy" arguments of hooks that repeat in a lot of internal
plugins.

Not all of the arguments are annotated fully for now.
This commit is contained in:
Ran Benita 2020-05-01 14:40:15 +03:00
parent ff8b7884e8
commit 0fb081aec6
26 changed files with 185 additions and 103 deletions

View File

@ -13,12 +13,13 @@ from _pytest.assertion.rewrite import assertstate_key
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
if TYPE_CHECKING: if TYPE_CHECKING:
from _pytest.main import Session from _pytest.main import Session
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("debugconfig") group = parser.getgroup("debugconfig")
group.addoption( group.addoption(
"--assert", "--assert",
@ -167,7 +168,7 @@ def pytest_runtest_protocol(item):
util._reprcompare, util._assertion_pass = saved_assert_hooks util._reprcompare, util._assertion_pass = saved_assert_hooks
def pytest_sessionfinish(session): def pytest_sessionfinish(session: "Session") -> None:
assertstate = session.config._store.get(assertstate_key, None) assertstate = session.config._store.get(assertstate_key, None)
if assertstate: if assertstate:
if assertstate.hook is not None: if assertstate.hook is not None:

View File

@ -11,6 +11,7 @@ from typing import Generator
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Set from typing import Set
from typing import Union
import attr import attr
import py import py
@ -24,6 +25,8 @@ from _pytest import nodes
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest.compat import order_preserving_dict from _pytest.compat import order_preserving_dict
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser
from _pytest.main import Session from _pytest.main import Session
from _pytest.python import Module from _pytest.python import Module
@ -329,11 +332,12 @@ class LFPlugin:
else: else:
self._report_status += "not deselecting items." self._report_status += "not deselecting items."
def pytest_sessionfinish(self, session): def pytest_sessionfinish(self, session: Session) -> None:
config = self.config config = self.config
if config.getoption("cacheshow") or hasattr(config, "slaveinput"): if config.getoption("cacheshow") or hasattr(config, "slaveinput"):
return return
assert config.cache is not None
saved_lastfailed = config.cache.get("cache/lastfailed", {}) saved_lastfailed = config.cache.get("cache/lastfailed", {})
if saved_lastfailed != self.lastfailed: if saved_lastfailed != self.lastfailed:
config.cache.set("cache/lastfailed", self.lastfailed) config.cache.set("cache/lastfailed", self.lastfailed)
@ -382,7 +386,7 @@ class NFPlugin:
config.cache.set("cache/nodeids", sorted(self.cached_nodeids)) config.cache.set("cache/nodeids", sorted(self.cached_nodeids))
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption( group.addoption(
"--lf", "--lf",
@ -440,16 +444,18 @@ def pytest_addoption(parser):
) )
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
if config.option.cacheshow: if config.option.cacheshow:
from _pytest.main import wrap_session from _pytest.main import wrap_session
return wrap_session(config, cacheshow) return wrap_session(config, cacheshow)
return None
@pytest.hookimpl(tryfirst=True) @pytest.hookimpl(tryfirst=True)
def pytest_configure(config: Config) -> None: def pytest_configure(config: Config) -> None:
config.cache = Cache.for_config(config) # Type ignored: pending mechanism to store typed objects scoped to config.
config.cache = Cache.for_config(config) # type: ignore # noqa: F821
config.pluginmanager.register(LFPlugin(config), "lfplugin") config.pluginmanager.register(LFPlugin(config), "lfplugin")
config.pluginmanager.register(NFPlugin(config), "nfplugin") config.pluginmanager.register(NFPlugin(config), "nfplugin")

View File

@ -16,6 +16,7 @@ from typing import Tuple
import pytest import pytest
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config from _pytest.config import Config
from _pytest.config.argparsing import Parser
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Literal from typing_extensions import Literal
@ -23,7 +24,7 @@ if TYPE_CHECKING:
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"] _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group._addoption( group._addoption(
"--capture", "--capture",

View File

@ -407,7 +407,7 @@ class PytestPluginManager(PluginManager):
"""Return True if the plugin with the given name is registered.""" """Return True if the plugin with the given name is registered."""
return bool(self.get_plugin(name)) return bool(self.get_plugin(name))
def pytest_configure(self, config): def pytest_configure(self, config: "Config") -> None:
# XXX now that the pluginmanager exposes hookimpl(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( config.addinivalue_line(
@ -868,7 +868,9 @@ class Config:
def get_terminal_writer(self): def get_terminal_writer(self):
return self.pluginmanager.get_plugin("terminalreporter")._tw return self.pluginmanager.get_plugin("terminalreporter")._tw
def pytest_cmdline_parse(self, pluginmanager, args): def pytest_cmdline_parse(
self, pluginmanager: PytestPluginManager, args: List[str]
) -> object:
try: try:
self.parse(args) self.parse(args)
except UsageError: except UsageError:

View File

@ -4,8 +4,11 @@ import functools
import sys import sys
from _pytest import outcomes from _pytest import outcomes
from _pytest.config import Config
from _pytest.config import ConftestImportFailure from _pytest.config import ConftestImportFailure
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config import PytestPluginManager
from _pytest.config.argparsing import Parser
from _pytest.config.exceptions import UsageError from _pytest.config.exceptions import UsageError
@ -20,7 +23,7 @@ def _validate_usepdb_cls(value):
return (modname, classname) return (modname, classname)
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group._addoption( group._addoption(
"--pdb", "--pdb",
@ -44,7 +47,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
import pdb import pdb
if config.getvalue("trace"): if config.getvalue("trace"):
@ -74,8 +77,8 @@ def pytest_configure(config):
class pytestPDB: class pytestPDB:
""" Pseudo PDB that defers to the real pdb. """ """ Pseudo PDB that defers to the real pdb. """
_pluginmanager = None _pluginmanager = None # type: PytestPluginManager
_config = None _config = None # type: Config
_saved = [] # type: list _saved = [] # type: list
_recursive_debug = 0 _recursive_debug = 0
_wrapped_pdb_cls = None _wrapped_pdb_cls = None

View File

@ -23,6 +23,7 @@ from _pytest._code.code import TerminalRepr
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest.compat import safe_getattr from _pytest.compat import safe_getattr
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.outcomes import OutcomeException from _pytest.outcomes import OutcomeException
from _pytest.python_api import approx from _pytest.python_api import approx
@ -52,7 +53,7 @@ RUNNER_CLASS = None
CHECKER_CLASS = None # type: Optional[Type[doctest.OutputChecker]] CHECKER_CLASS = None # type: Optional[Type[doctest.OutputChecker]]
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
parser.addini( parser.addini(
"doctest_optionflags", "doctest_optionflags",
"option flags for doctests", "option flags for doctests",
@ -102,7 +103,7 @@ def pytest_addoption(parser):
) )
def pytest_unconfigure(): def pytest_unconfigure() -> None:
global RUNNER_CLASS global RUNNER_CLASS
RUNNER_CLASS = None RUNNER_CLASS = None

View File

@ -4,13 +4,15 @@ import sys
from typing import TextIO from typing import TextIO
import pytest import pytest
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.store import StoreKey from _pytest.store import StoreKey
fault_handler_stderr_key = StoreKey[TextIO]() fault_handler_stderr_key = StoreKey[TextIO]()
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
help = ( help = (
"Dump the traceback of all threads if a test takes " "Dump the traceback of all threads if a test takes "
"more than TIMEOUT seconds to finish." "more than TIMEOUT seconds to finish."
@ -18,7 +20,7 @@ def pytest_addoption(parser):
parser.addini("faulthandler_timeout", help, default=0.0) parser.addini("faulthandler_timeout", help, default=0.0)
def pytest_configure(config): def pytest_configure(config: Config) -> None:
import faulthandler import faulthandler
if not faulthandler.is_enabled(): if not faulthandler.is_enabled():
@ -46,14 +48,14 @@ class FaultHandlerHooks:
"""Implements hooks that will actually install fault handler before tests execute, """Implements hooks that will actually install fault handler before tests execute,
as well as correctly handle pdb and internal errors.""" as well as correctly handle pdb and internal errors."""
def pytest_configure(self, config): def pytest_configure(self, config: Config) -> None:
import faulthandler import faulthandler
stderr_fd_copy = os.dup(self._get_stderr_fileno()) stderr_fd_copy = os.dup(self._get_stderr_fileno())
config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w") config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w")
faulthandler.enable(file=config._store[fault_handler_stderr_key]) faulthandler.enable(file=config._store[fault_handler_stderr_key])
def pytest_unconfigure(self, config): def pytest_unconfigure(self, config: Config) -> None:
import faulthandler import faulthandler
faulthandler.disable() faulthandler.disable()

View File

@ -29,6 +29,7 @@ from _pytest.compat import NOTSET
from _pytest.compat import order_preserving_dict from _pytest.compat import order_preserving_dict
from _pytest.compat import safe_getattr from _pytest.compat import safe_getattr
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config.argparsing import Parser
from _pytest.deprecated import FILLFUNCARGS from _pytest.deprecated import FILLFUNCARGS
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
from _pytest.deprecated import FUNCARGNAMES from _pytest.deprecated import FUNCARGNAMES
@ -49,7 +50,7 @@ class PseudoFixtureDef:
scope = attr.ib() scope = attr.ib()
def pytest_sessionstart(session: "Session"): def pytest_sessionstart(session: "Session") -> None:
import _pytest.python import _pytest.python
import _pytest.nodes import _pytest.nodes
@ -1202,7 +1203,7 @@ def pytestconfig(request):
return request.config return request.config
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
parser.addini( parser.addini(
"usefixtures", "usefixtures",
type="args", type="args",

View File

@ -2,11 +2,16 @@
import os import os
import sys import sys
from argparse import Action from argparse import Action
from typing import Optional
from typing import Union
import py import py
import pytest import pytest
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import PrintHelp from _pytest.config import PrintHelp
from _pytest.config.argparsing import Parser
class HelpAction(Action): class HelpAction(Action):
@ -36,7 +41,7 @@ class HelpAction(Action):
raise PrintHelp raise PrintHelp
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("debugconfig") group = parser.getgroup("debugconfig")
group.addoption( group.addoption(
"--version", "--version",
@ -109,7 +114,7 @@ def pytest_cmdline_parse():
undo_tracing = config.pluginmanager.enable_tracing() undo_tracing = config.pluginmanager.enable_tracing()
sys.stderr.write("writing pytestdebug information to %s\n" % path) sys.stderr.write("writing pytestdebug information to %s\n" % path)
def unset_tracing(): def unset_tracing() -> None:
debugfile.close() debugfile.close()
sys.stderr.write("wrote pytestdebug information to %s\n" % debugfile.name) sys.stderr.write("wrote pytestdebug information to %s\n" % debugfile.name)
config.trace.root.setwriter(None) config.trace.root.setwriter(None)
@ -133,7 +138,7 @@ def showversion(config):
sys.stderr.write("pytest {}\n".format(pytest.__version__)) sys.stderr.write("pytest {}\n".format(pytest.__version__))
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
if config.option.version > 0: if config.option.version > 0:
showversion(config) showversion(config)
return 0 return 0
@ -142,9 +147,10 @@ def pytest_cmdline_main(config):
showhelp(config) showhelp(config)
config._ensure_unconfigure() config._ensure_unconfigure()
return 0 return 0
return None
def showhelp(config): def showhelp(config: Config) -> None:
import textwrap import textwrap
reporter = config.pluginmanager.get_plugin("terminalreporter") reporter = config.pluginmanager.get_plugin("terminalreporter")

View File

@ -1,5 +1,6 @@
""" 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 typing import Any from typing import Any
from typing import List
from typing import Mapping from typing import Mapping
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
@ -14,10 +15,14 @@ from _pytest.compat import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
import warnings import warnings
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import PytestPluginManager
from _pytest.config import _PluggyPlugin
from _pytest.config.argparsing import Parser
from _pytest.main import Session from _pytest.main import Session
from _pytest.python import Metafunc
from _pytest.reports import BaseReport from _pytest.reports import BaseReport
hookspec = HookspecMarker("pytest") hookspec = HookspecMarker("pytest")
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@ -26,7 +31,7 @@ hookspec = HookspecMarker("pytest")
@hookspec(historic=True) @hookspec(historic=True)
def pytest_addhooks(pluginmanager): def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None:
"""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.add_hookspecs(module_or_class, prefix)``. ``pluginmanager.add_hookspecs(module_or_class, prefix)``.
@ -39,7 +44,9 @@ def pytest_addhooks(pluginmanager):
@hookspec(historic=True) @hookspec(historic=True)
def pytest_plugin_registered(plugin, manager): def pytest_plugin_registered(
plugin: "_PluggyPlugin", manager: "PytestPluginManager"
) -> None:
""" a new pytest plugin got registered. """ a new pytest plugin got registered.
:param plugin: the plugin module or instance :param plugin: the plugin module or instance
@ -51,7 +58,7 @@ def pytest_plugin_registered(plugin, manager):
@hookspec(historic=True) @hookspec(historic=True)
def pytest_addoption(parser, pluginmanager): def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> None:
"""register argparse-style options and ini-style config values, """register argparse-style options and ini-style config values,
called once at the beginning of a test run. called once at the beginning of a test run.
@ -89,7 +96,7 @@ def pytest_addoption(parser, pluginmanager):
@hookspec(historic=True) @hookspec(historic=True)
def pytest_configure(config): def pytest_configure(config: "Config") -> None:
""" """
Allows plugins and conftest files to perform initial configuration. Allows plugins and conftest files to perform initial configuration.
@ -113,7 +120,9 @@ def pytest_configure(config):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_cmdline_parse(pluginmanager, args): def pytest_cmdline_parse(
pluginmanager: "PytestPluginManager", args: List[str]
) -> Optional[object]:
"""return initialized config object, parsing the specified args. """return initialized config object, parsing the specified args.
Stops at first non-None result, see :ref:`firstresult` Stops at first non-None result, see :ref:`firstresult`
@ -127,7 +136,7 @@ def pytest_cmdline_parse(pluginmanager, args):
""" """
def pytest_cmdline_preparse(config, args): def pytest_cmdline_preparse(config: "Config", args: List[str]) -> None:
"""(**Deprecated**) modify command line arguments before option parsing. """(**Deprecated**) modify command line arguments before option parsing.
This hook is considered deprecated and will be removed in a future pytest version. Consider This hook is considered deprecated and will be removed in a future pytest version. Consider
@ -142,7 +151,7 @@ def pytest_cmdline_preparse(config, args):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_cmdline_main(config): def pytest_cmdline_main(config: "Config") -> "Optional[Union[ExitCode, int]]":
""" 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.
@ -155,7 +164,9 @@ def pytest_cmdline_main(config):
""" """
def pytest_load_initial_conftests(early_config, parser, args): def pytest_load_initial_conftests(
early_config: "Config", parser: "Parser", args: List[str]
) -> None:
""" implements the loading of initial conftest files ahead """ implements the loading of initial conftest files ahead
of command line option parsing. of command line option parsing.
@ -198,7 +209,7 @@ def pytest_collection(session: "Session") -> Optional[Any]:
""" """
def pytest_collection_modifyitems(session, config, items): def pytest_collection_modifyitems(session: "Session", config: "Config", items):
""" called after collection has been performed, may filter or re-order """ called after collection has been performed, may filter or re-order
the items in-place. the items in-place.
@ -208,7 +219,7 @@ def pytest_collection_modifyitems(session, config, items):
""" """
def pytest_collection_finish(session): def pytest_collection_finish(session: "Session"):
""" called after collection has been performed and modified. """ called after collection has been performed and modified.
:param _pytest.main.Session session: the pytest session object :param _pytest.main.Session session: the pytest session object
@ -216,7 +227,7 @@ def pytest_collection_finish(session):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_ignore_collect(path, config): def pytest_ignore_collect(path, config: "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.
@ -304,12 +315,12 @@ def pytest_pyfunc_call(pyfuncitem):
Stops at first non-None result, see :ref:`firstresult` """ Stops at first non-None result, see :ref:`firstresult` """
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc: "Metafunc") -> None:
""" generate (multiple) parametrized calls to a test function.""" """ generate (multiple) parametrized calls to a test function."""
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_make_parametrize_id(config, val, argname): def pytest_make_parametrize_id(config: "Config", val, argname) -> Optional[str]:
"""Return a user-friendly string representation of the given ``val`` that will be used """Return a user-friendly string representation of the given ``val`` that will be used
by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``. by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``.
The parameter name is available as ``argname``, if required. The parameter name is available as ``argname``, if required.
@ -328,7 +339,7 @@ def pytest_make_parametrize_id(config, val, argname):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_runtestloop(session): def pytest_runtestloop(session: "Session"):
""" called for performing the main runtest loop """ called for performing the main runtest loop
(after collection finished). (after collection finished).
@ -411,7 +422,7 @@ def pytest_runtest_logreport(report):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_report_to_serializable(config, report): def pytest_report_to_serializable(config: "Config", report):
""" """
Serializes the given report object into a data structure suitable for sending Serializes the given report object into a data structure suitable for sending
over the wire, e.g. converted to JSON. over the wire, e.g. converted to JSON.
@ -419,7 +430,7 @@ def pytest_report_to_serializable(config, report):
@hookspec(firstresult=True) @hookspec(firstresult=True)
def pytest_report_from_serializable(config, data): def pytest_report_from_serializable(config: "Config", data):
""" """
Restores a report object previously serialized with pytest_report_to_serializable(). Restores a report object previously serialized with pytest_report_to_serializable().
""" """
@ -456,7 +467,7 @@ def pytest_fixture_post_finalizer(fixturedef, request):
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def pytest_sessionstart(session): def pytest_sessionstart(session: "Session") -> None:
""" called after the ``Session`` object has been created and before performing collection """ called after the ``Session`` object has been created and before performing collection
and entering the run test loop. and entering the run test loop.
@ -464,7 +475,9 @@ def pytest_sessionstart(session):
""" """
def pytest_sessionfinish(session, exitstatus): def pytest_sessionfinish(
session: "Session", exitstatus: "Union[int, ExitCode]"
) -> None:
""" called after whole test run finished, right before returning the exit status to the system. """ called after whole test run finished, right before returning the exit status to the system.
:param _pytest.main.Session session: the pytest session object :param _pytest.main.Session session: the pytest session object
@ -472,7 +485,7 @@ def pytest_sessionfinish(session, exitstatus):
""" """
def pytest_unconfigure(config): def pytest_unconfigure(config: "Config") -> None:
""" called before test process is exited. """ called before test process is exited.
:param _pytest.config.Config config: pytest config object :param _pytest.config.Config config: pytest config object
@ -484,7 +497,7 @@ def pytest_unconfigure(config):
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def pytest_assertrepr_compare(config, op, left, right): def pytest_assertrepr_compare(config: "Config", op, left, right):
"""return explanation for comparisons in failing assert expressions. """return explanation for comparisons in failing assert expressions.
Return None for no custom explanation, otherwise return a list Return None for no custom explanation, otherwise return a list
@ -539,7 +552,7 @@ def pytest_assertion_pass(item, lineno, orig, expl):
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def pytest_report_header(config, startdir): def pytest_report_header(config: "Config", startdir):
""" return a string or list of strings to be displayed as header info for terminal reporting. """ return a string or list of strings to be displayed as header info for terminal reporting.
:param _pytest.config.Config config: pytest config object :param _pytest.config.Config config: pytest config object
@ -560,7 +573,7 @@ def pytest_report_header(config, startdir):
""" """
def pytest_report_collectionfinish(config, startdir, items): def pytest_report_collectionfinish(config: "Config", startdir, items):
""" """
.. versionadded:: 3.2 .. versionadded:: 3.2
@ -610,7 +623,7 @@ def pytest_report_teststatus(
""" """
def pytest_terminal_summary(terminalreporter, exitstatus, config): def pytest_terminal_summary(terminalreporter, exitstatus, config: "Config"):
"""Add a section to terminal summary reporting. """Add a section to terminal summary reporting.
:param _pytest.terminal.TerminalReporter terminalreporter: the internal terminal reporter object :param _pytest.terminal.TerminalReporter terminalreporter: the internal terminal reporter object
@ -723,7 +736,7 @@ def pytest_exception_interact(node, call, report):
""" """
def pytest_enter_pdb(config, pdb): def pytest_enter_pdb(config: "Config", pdb):
""" called upon pdb.set_trace(), can be used by plugins to take special """ called upon pdb.set_trace(), can be used by plugins to take special
action just before the python debugger enters in interactive mode. action just before the python debugger enters in interactive mode.
@ -732,7 +745,7 @@ def pytest_enter_pdb(config, pdb):
""" """
def pytest_leave_pdb(config, pdb): def pytest_leave_pdb(config: "Config", pdb):
""" called when leaving pdb (e.g. with continue after pdb.set_trace()). """ called when leaving pdb (e.g. with continue after pdb.set_trace()).
Can be used by plugins to take special action just after the python Can be used by plugins to take special action just after the python

View File

@ -21,7 +21,9 @@ import pytest
from _pytest import deprecated from _pytest import deprecated
from _pytest import nodes from _pytest import nodes
from _pytest import timing from _pytest import timing
from _pytest.config import Config
from _pytest.config import filename_arg from _pytest.config import filename_arg
from _pytest.config.argparsing import Parser
from _pytest.store import StoreKey from _pytest.store import StoreKey
from _pytest.warnings import _issue_warning_captured from _pytest.warnings import _issue_warning_captured
@ -361,7 +363,7 @@ def record_testsuite_property(request):
return record_func return record_func
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting") group = parser.getgroup("terminal reporting")
group.addoption( group.addoption(
"--junitxml", "--junitxml",
@ -406,7 +408,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
xmlpath = config.option.xmlpath xmlpath = config.option.xmlpath
# prevent opening xmllog on slave nodes (xdist) # prevent opening xmllog on slave nodes (xdist)
if xmlpath and not hasattr(config, "slaveinput"): if xmlpath and not hasattr(config, "slaveinput"):
@ -426,7 +428,7 @@ def pytest_configure(config):
config.pluginmanager.register(config._store[xml_key]) config.pluginmanager.register(config._store[xml_key])
def pytest_unconfigure(config): def pytest_unconfigure(config: Config) -> None:
xml = config._store.get(xml_key, None) xml = config._store.get(xml_key, None)
if xml: if xml:
del config._store[xml_key] del config._store[xml_key]
@ -624,10 +626,10 @@ class LogXML:
reporter.attrs.update(classname="pytest", name="internal") reporter.attrs.update(classname="pytest", name="internal")
reporter._add_simple(Junit.error, "internal error", excrepr) reporter._add_simple(Junit.error, "internal error", excrepr)
def pytest_sessionstart(self): def pytest_sessionstart(self) -> None:
self.suite_start_time = timing.time() self.suite_start_time = timing.time()
def pytest_sessionfinish(self): def pytest_sessionfinish(self) -> None:
dirname = os.path.dirname(os.path.abspath(self.logfile)) dirname = os.path.dirname(os.path.abspath(self.logfile))
if not os.path.isdir(dirname): if not os.path.isdir(dirname):
os.makedirs(dirname) os.makedirs(dirname)

View File

@ -19,6 +19,7 @@ from _pytest.compat import nullcontext
from _pytest.config import _strtobool from _pytest.config import _strtobool
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import create_terminal_writer from _pytest.config import create_terminal_writer
from _pytest.config.argparsing import Parser
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.store import StoreKey from _pytest.store import StoreKey
@ -180,7 +181,7 @@ def get_option_ini(config, *names):
return ret return ret
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
"""Add options to control log capturing.""" """Add options to control log capturing."""
group = parser.getgroup("logging") group = parser.getgroup("logging")
@ -478,7 +479,7 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
# run after terminalreporter/capturemanager are configured # run after terminalreporter/capturemanager are configured
@pytest.hookimpl(trylast=True) @pytest.hookimpl(trylast=True)
def pytest_configure(config): def pytest_configure(config: Config) -> None:
config.pluginmanager.register(LoggingPlugin(config), "logging-plugin") config.pluginmanager.register(LoggingPlugin(config), "logging-plugin")
@ -601,7 +602,7 @@ class LoggingPlugin:
return True return True
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_sessionstart(self): def pytest_sessionstart(self) -> Generator[None, None, None]:
self.log_cli_handler.set_when("sessionstart") self.log_cli_handler.set_when("sessionstart")
with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_cli_handler, level=self.log_cli_level):
@ -679,7 +680,7 @@ class LoggingPlugin:
self.log_cli_handler.set_when("finish") self.log_cli_handler.set_when("finish")
@pytest.hookimpl(hookwrapper=True, tryfirst=True) @pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_sessionfinish(self): def pytest_sessionfinish(self) -> Generator[None, None, None]:
self.log_cli_handler.set_when("sessionfinish") self.log_cli_handler.set_when("sessionfinish")
with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_cli_handler, level=self.log_cli_level):
@ -687,7 +688,7 @@ class LoggingPlugin:
yield yield
@pytest.hookimpl @pytest.hookimpl
def pytest_unconfigure(self): def pytest_unconfigure(self) -> None:
# Close the FileHandler explicitly. # Close the FileHandler explicitly.
# (logging.shutdown might have lost the weakref?!) # (logging.shutdown might have lost the weakref?!)
self.log_file_handler.close() self.log_file_handler.close()

View File

@ -18,8 +18,10 @@ from .structures import MarkGenerator
from .structures import ParameterSet from .structures import ParameterSet
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config import UsageError from _pytest.config import UsageError
from _pytest.config.argparsing import Parser
from _pytest.deprecated import MINUS_K_COLON from _pytest.deprecated import MINUS_K_COLON
from _pytest.deprecated import MINUS_K_DASH from _pytest.deprecated import MINUS_K_DASH
from _pytest.store import StoreKey from _pytest.store import StoreKey
@ -27,6 +29,7 @@ from _pytest.store import StoreKey
if TYPE_CHECKING: if TYPE_CHECKING:
from _pytest.nodes import Item from _pytest.nodes import Item
__all__ = ["Mark", "MarkDecorator", "MarkGenerator", "get_empty_parameterset_mark"] __all__ = ["Mark", "MarkDecorator", "MarkGenerator", "get_empty_parameterset_mark"]
@ -57,7 +60,7 @@ def param(
return ParameterSet.param(*values, marks=marks, id=id) return ParameterSet.param(*values, marks=marks, id=id)
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group._addoption( group._addoption(
"-k", "-k",
@ -100,7 +103,7 @@ def pytest_addoption(parser):
@hookimpl(tryfirst=True) @hookimpl(tryfirst=True)
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
import _pytest.config import _pytest.config
if config.option.markers: if config.option.markers:
@ -116,6 +119,8 @@ def pytest_cmdline_main(config):
config._ensure_unconfigure() config._ensure_unconfigure()
return 0 return 0
return None
@attr.s(slots=True) @attr.s(slots=True)
class KeywordMatcher: class KeywordMatcher:
@ -254,7 +259,7 @@ def pytest_collection_modifyitems(items, config: Config) -> None:
deselect_by_mark(items, config) deselect_by_mark(items, config)
def pytest_configure(config): def pytest_configure(config: Config) -> None:
config._store[old_mark_config_key] = MARK_GEN._config config._store[old_mark_config_key] = MARK_GEN._config
MARK_GEN._config = config MARK_GEN._config = config
@ -267,5 +272,5 @@ def pytest_configure(config):
) )
def pytest_unconfigure(config): def pytest_unconfigure(config: Config) -> None:
MARK_GEN._config = config._store.get(old_mark_config_key, None) MARK_GEN._config = config._store.get(old_mark_config_key, None)

View File

@ -374,7 +374,7 @@ class MarkGenerator:
applies a 'slowtest' :class:`Mark` on ``test_function``. applies a 'slowtest' :class:`Mark` on ``test_function``.
""" """
_config = None _config = None # type: Optional[Config]
_markers = set() # type: Set[str] _markers = set() # type: Set[str]
def __getattr__(self, name: str) -> MarkDecorator: def __getattr__(self, name: str) -> MarkDecorator:

View File

@ -123,7 +123,7 @@ class Node(metaclass=NodeMeta):
#: the pytest config object #: the pytest config object
if config: if config:
self.config = config self.config = config # type: Config
else: else:
if not parent: if not parent:
raise TypeError("config or parent must be provided") raise TypeError("config or parent must be provided")

View File

@ -4,13 +4,15 @@ from io import StringIO
from typing import IO from typing import IO
import pytest import pytest
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.store import StoreKey from _pytest.store import StoreKey
pastebinfile_key = StoreKey[IO[bytes]]() pastebinfile_key = StoreKey[IO[bytes]]()
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting") group = parser.getgroup("terminal reporting")
group._addoption( group._addoption(
"--pastebin", "--pastebin",
@ -24,7 +26,7 @@ def pytest_addoption(parser):
@pytest.hookimpl(trylast=True) @pytest.hookimpl(trylast=True)
def pytest_configure(config): def pytest_configure(config: Config) -> None:
if config.option.pastebin == "all": if config.option.pastebin == "all":
tr = config.pluginmanager.getplugin("terminalreporter") tr = config.pluginmanager.getplugin("terminalreporter")
# if no terminal reporter plugin is present, nothing we can do here; # if no terminal reporter plugin is present, nothing we can do here;
@ -44,7 +46,7 @@ def pytest_configure(config):
tr._tw.write = tee_write tr._tw.write = tee_write
def pytest_unconfigure(config): def pytest_unconfigure(config: Config) -> None:
if pastebinfile_key in config._store: if pastebinfile_key in config._store:
pastebinfile = config._store[pastebinfile_key] pastebinfile = config._store[pastebinfile_key]
# get terminal contents and delete file # get terminal contents and delete file

View File

@ -31,6 +31,7 @@ from _pytest.compat import TYPE_CHECKING
from _pytest.config import _PluggyPlugin from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.main import Session from _pytest.main import Session
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
@ -53,7 +54,7 @@ IGNORE_PAM = [ # filenames added when obtaining details about the current user
] ]
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
parser.addoption( parser.addoption(
"--lsof", "--lsof",
action="store_true", action="store_true",
@ -78,7 +79,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
if config.getvalue("lsof"): if config.getvalue("lsof"):
checker = LsofFdLeakChecker() checker = LsofFdLeakChecker()
if checker.matching_platform(): if checker.matching_platform():
@ -938,7 +939,7 @@ class Testdir:
rec = [] rec = []
class Collect: class Collect:
def pytest_configure(x, config): def pytest_configure(x, config: Config) -> None:
rec.append(self.make_hook_recorder(config.pluginmanager)) rec.append(self.make_hook_recorder(config.pluginmanager))
plugins.append(Collect()) plugins.append(Collect())

View File

@ -16,6 +16,7 @@ from typing import Dict
from typing import Iterable from typing import Iterable
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Set
from typing import Tuple from typing import Tuple
from typing import Union from typing import Union
@ -42,9 +43,12 @@ from _pytest.compat import safe_getattr
from _pytest.compat import safe_isclass from _pytest.compat import safe_isclass
from _pytest.compat import STRING_TYPES from _pytest.compat import STRING_TYPES
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
from _pytest.deprecated import FUNCARGNAMES from _pytest.deprecated import FUNCARGNAMES
from _pytest.fixtures import FuncFixtureInfo from _pytest.fixtures import FuncFixtureInfo
from _pytest.main import Session
from _pytest.mark import MARK_GEN from _pytest.mark import MARK_GEN
from _pytest.mark import ParameterSet from _pytest.mark import ParameterSet
from _pytest.mark.structures import get_unpacked_marks from _pytest.mark.structures import get_unpacked_marks
@ -57,7 +61,7 @@ from _pytest.warning_types import PytestCollectionWarning
from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption( group.addoption(
"--fixtures", "--fixtures",
@ -112,13 +116,14 @@ def pytest_addoption(parser):
) )
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
if config.option.showfixtures: if config.option.showfixtures:
showfixtures(config) showfixtures(config)
return 0 return 0
if config.option.show_fixtures_per_test: if config.option.show_fixtures_per_test:
show_fixtures_per_test(config) show_fixtures_per_test(config)
return 0 return 0
return None
def pytest_generate_tests(metafunc: "Metafunc") -> None: def pytest_generate_tests(metafunc: "Metafunc") -> None:
@ -127,7 +132,7 @@ def pytest_generate_tests(metafunc: "Metafunc") -> None:
metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker) # type: ignore[misc] metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker) # type: ignore[misc]
def pytest_configure(config): def pytest_configure(config: Config) -> None:
config.addinivalue_line( config.addinivalue_line(
"markers", "markers",
"parametrize(argnames, argvalues): call a test function multiple " "parametrize(argnames, argvalues): call a test function multiple "
@ -1308,13 +1313,13 @@ def _show_fixtures_per_test(config, session):
write_item(session_item) write_item(session_item)
def showfixtures(config): def showfixtures(config: Config) -> Union[int, ExitCode]:
from _pytest.main import wrap_session from _pytest.main import wrap_session
return wrap_session(config, _showfixtures_main) return wrap_session(config, _showfixtures_main)
def _showfixtures_main(config, session): def _showfixtures_main(config: Config, session: Session) -> None:
import _pytest.config import _pytest.config
session.perform_collect() session.perform_collect()
@ -1325,7 +1330,7 @@ def _showfixtures_main(config, session):
fm = session._fixturemanager fm = session._fixturemanager
available = [] available = []
seen = set() seen = set() # type: Set[Tuple[str, str]]
for argname, fixturedefs in fm._arg2fixturedefs.items(): for argname, fixturedefs in fm._arg2fixturedefs.items():
assert fixturedefs is not None assert fixturedefs is not None

View File

@ -5,13 +5,15 @@ import os
import py import py
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.store import StoreKey from _pytest.store import StoreKey
resultlog_key = StoreKey["ResultLog"]() resultlog_key = StoreKey["ResultLog"]()
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting", "resultlog plugin options") group = parser.getgroup("terminal reporting", "resultlog plugin options")
group.addoption( group.addoption(
"--resultlog", "--resultlog",
@ -23,7 +25,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
resultlog = config.option.resultlog resultlog = config.option.resultlog
# prevent opening resultlog on slave nodes (xdist) # prevent opening resultlog on slave nodes (xdist)
if resultlog and not hasattr(config, "slaveinput"): if resultlog and not hasattr(config, "slaveinput"):
@ -40,7 +42,7 @@ def pytest_configure(config):
_issue_warning_captured(RESULT_LOG, config.hook, stacklevel=2) _issue_warning_captured(RESULT_LOG, config.hook, stacklevel=2)
def pytest_unconfigure(config): def pytest_unconfigure(config: Config) -> None:
resultlog = config._store.get(resultlog_key, None) resultlog = config._store.get(resultlog_key, None)
if resultlog: if resultlog:
resultlog.logfile.close() resultlog.logfile.close()

View File

@ -17,6 +17,7 @@ from _pytest import timing
from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ExceptionInfo from _pytest._code.code import ExceptionInfo
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config.argparsing import Parser
from _pytest.nodes import Collector from _pytest.nodes import Collector
from _pytest.nodes import Node from _pytest.nodes import Node
from _pytest.outcomes import Exit from _pytest.outcomes import Exit
@ -27,11 +28,13 @@ if TYPE_CHECKING:
from typing import Type from typing import Type
from typing_extensions import Literal from typing_extensions import Literal
from _pytest.main import Session
# #
# pytest plugin hooks # pytest plugin hooks
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting", "reporting", after="general") group = parser.getgroup("terminal reporting", "reporting", after="general")
group.addoption( group.addoption(
"--durations", "--durations",
@ -75,11 +78,11 @@ def pytest_terminal_summary(terminalreporter):
tr.write_line("{:02.2f}s {:<8} {}".format(rep.duration, rep.when, rep.nodeid)) tr.write_line("{:02.2f}s {:<8} {}".format(rep.duration, rep.when, rep.nodeid))
def pytest_sessionstart(session): def pytest_sessionstart(session: "Session") -> None:
session._setupstate = SetupState() session._setupstate = SetupState()
def pytest_sessionfinish(session): def pytest_sessionfinish(session: "Session") -> None:
session._setupstate.teardown_all() session._setupstate.teardown_all()

View File

@ -1,8 +1,14 @@
from typing import Optional
from typing import Union
import pytest import pytest
from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("debugconfig") group = parser.getgroup("debugconfig")
group.addoption( group.addoption(
"--setuponly", "--setuponly",
@ -76,6 +82,7 @@ def _show_fixture_action(fixturedef, msg):
@pytest.hookimpl(tryfirst=True) @pytest.hookimpl(tryfirst=True)
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
if config.option.setuponly: if config.option.setuponly:
config.option.setupshow = True config.option.setupshow = True
return None

View File

@ -1,7 +1,13 @@
from typing import Optional
from typing import Union
import pytest import pytest
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("debugconfig") group = parser.getgroup("debugconfig")
group.addoption( group.addoption(
"--setupplan", "--setupplan",
@ -19,10 +25,12 @@ def pytest_fixture_setup(fixturedef, request):
my_cache_key = fixturedef.cache_key(request) my_cache_key = fixturedef.cache_key(request)
fixturedef.cached_result = (None, my_cache_key, None) fixturedef.cached_result = (None, my_cache_key, None)
return fixturedef.cached_result return fixturedef.cached_result
return None
@pytest.hookimpl(tryfirst=True) @pytest.hookimpl(tryfirst=True)
def pytest_cmdline_main(config): def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
if config.option.setupplan: if config.option.setupplan:
config.option.setuponly = True config.option.setuponly = True
config.option.setupshow = True config.option.setupshow = True
return None

View File

@ -1,5 +1,7 @@
""" support for skip/xfail functions and markers. """ """ support for skip/xfail functions and markers. """
from _pytest.config import Config
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
from _pytest.mark.evaluate import MarkEvaluator from _pytest.mark.evaluate import MarkEvaluator
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.outcomes import skip from _pytest.outcomes import skip
@ -12,7 +14,7 @@ evalxfail_key = StoreKey[MarkEvaluator]()
unexpectedsuccess_key = StoreKey[str]() unexpectedsuccess_key = StoreKey[str]()
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption( group.addoption(
"--runxfail", "--runxfail",
@ -31,7 +33,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
if config.option.runxfail: if config.option.runxfail:
# yay a hack # yay a hack
import pytest import pytest
@ -42,7 +44,7 @@ def pytest_configure(config):
def nop(*args, **kwargs): def nop(*args, **kwargs):
pass pass
nop.Exception = xfail.Exception nop.Exception = xfail.Exception # type: ignore[attr-defined] # noqa: F821
setattr(pytest, "xfail", nop) setattr(pytest, "xfail", nop)
config.addinivalue_line( config.addinivalue_line(

View File

@ -1,7 +1,10 @@
import pytest import pytest
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.main import Session
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption( group.addoption(
"--sw", "--sw",
@ -19,7 +22,7 @@ def pytest_addoption(parser):
@pytest.hookimpl @pytest.hookimpl
def pytest_configure(config): def pytest_configure(config: Config) -> None:
config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin") config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin")
@ -34,7 +37,7 @@ class StepwisePlugin:
self.lastfailed = config.cache.get("cache/stepwise", None) self.lastfailed = config.cache.get("cache/stepwise", None)
self.skip = config.getvalue("stepwise_skip") self.skip = config.getvalue("stepwise_skip")
def pytest_sessionstart(self, session): def pytest_sessionstart(self, session: Session) -> None:
self.session = session self.session = session
def pytest_collection_modifyitems(self, session, config, items): def pytest_collection_modifyitems(self, session, config, items):
@ -100,7 +103,7 @@ class StepwisePlugin:
if self.active and self.config.getoption("verbose") >= 0 and self.report_status: if self.active and self.config.getoption("verbose") >= 0 and self.report_status:
return "stepwise: %s" % self.report_status return "stepwise: %s" % self.report_status
def pytest_sessionfinish(self, session): def pytest_sessionfinish(self, session: Session) -> None:
if self.active: if self.active:
self.config.cache.set("cache/stepwise", self.lastfailed) self.config.cache.set("cache/stepwise", self.lastfailed)
else: else:

View File

@ -17,6 +17,7 @@ from typing import Mapping
from typing import Optional from typing import Optional
from typing import Set from typing import Set
from typing import Tuple from typing import Tuple
from typing import Union
import attr import attr
import pluggy import pluggy
@ -29,8 +30,10 @@ from _pytest import timing
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest._io.wcwidth import wcswidth from _pytest._io.wcwidth import wcswidth
from _pytest.compat import order_preserving_dict from _pytest.compat import order_preserving_dict
from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser
from _pytest.deprecated import TERMINALWRITER_WRITER from _pytest.deprecated import TERMINALWRITER_WRITER
from _pytest.main import Session from _pytest.main import Session
from _pytest.reports import CollectReport from _pytest.reports import CollectReport
@ -77,7 +80,7 @@ class MoreQuietAction(argparse.Action):
namespace.quiet = getattr(namespace, "quiet", 0) + 1 namespace.quiet = getattr(namespace, "quiet", 0) + 1
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting", "reporting", after="general") group = parser.getgroup("terminal reporting", "reporting", after="general")
group._addoption( group._addoption(
"-v", "-v",
@ -423,7 +426,7 @@ class TerminalReporter:
) )
self._add_stats("warnings", [warning_report]) self._add_stats("warnings", [warning_report])
def pytest_plugin_registered(self, plugin): def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
if self.config.option.traceconfig: if self.config.option.traceconfig:
msg = "PLUGIN registered: {}".format(plugin) msg = "PLUGIN registered: {}".format(plugin)
# XXX this event may happen during setup/teardown time # XXX this event may happen during setup/teardown time
@ -717,7 +720,7 @@ class TerminalReporter:
self._tw.line("{}{}".format(indent + " ", line)) self._tw.line("{}{}".format(indent + " ", line))
@pytest.hookimpl(hookwrapper=True) @pytest.hookimpl(hookwrapper=True)
def pytest_sessionfinish(self, session: Session, exitstatus: ExitCode): def pytest_sessionfinish(self, session: Session, exitstatus: Union[int, ExitCode]):
outcome = yield outcome = yield
outcome.get_result() outcome.get_result()
self._tw.line("") self._tw.line("")
@ -752,10 +755,10 @@ class TerminalReporter:
# Display any extra warnings from teardown here (if any). # Display any extra warnings from teardown here (if any).
self.summary_warnings() self.summary_warnings()
def pytest_keyboard_interrupt(self, excinfo): def pytest_keyboard_interrupt(self, excinfo) -> None:
self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True)
def pytest_unconfigure(self): def pytest_unconfigure(self) -> None:
if hasattr(self, "_keyboardinterrupt_memo"): if hasattr(self, "_keyboardinterrupt_memo"):
self._report_keyboardinterrupt() self._report_keyboardinterrupt()

View File

@ -8,6 +8,8 @@ from typing import Tuple
import pytest import pytest
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.main import Session from _pytest.main import Session
if TYPE_CHECKING: if TYPE_CHECKING:
@ -49,7 +51,7 @@ def _parse_filter(
return (action, message, category, module, lineno) return (action, message, category, module, lineno)
def pytest_addoption(parser): def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("pytest-warnings") group = parser.getgroup("pytest-warnings")
group.addoption( group.addoption(
"-W", "-W",
@ -66,7 +68,7 @@ def pytest_addoption(parser):
) )
def pytest_configure(config): def pytest_configure(config: Config) -> None:
config.addinivalue_line( config.addinivalue_line(
"markers", "markers",
"filterwarnings(warning): add a warning filter to the given test. " "filterwarnings(warning): add a warning filter to the given test. "