hookspec: type annotate pytest_internalerror
Also switch to using ExceptionRepr instead of `Union[ReprExceptionInfo, ExceptionChainRepr]` which is somewhat annoying and less future proof.
This commit is contained in:
parent
7081ed19b8
commit
0256cb3aae
|
@ -928,8 +928,13 @@ class TerminalRepr:
|
|||
raise NotImplementedError()
|
||||
|
||||
|
||||
# This class is abstract -- only subclasses are instantiated.
|
||||
@attr.s(**{ATTRS_EQ_FIELD: False}) # type: ignore
|
||||
class ExceptionRepr(TerminalRepr):
|
||||
# Provided by in subclasses.
|
||||
reprcrash = None # type: Optional[ReprFileLocation]
|
||||
reprtraceback = None # type: ReprTraceback
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.sections = [] # type: List[Tuple[str, str, str]]
|
||||
|
||||
|
|
|
@ -753,7 +753,7 @@ class CaptureManager:
|
|||
self.stop_global_capturing()
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_internalerror(self, excinfo):
|
||||
def pytest_internalerror(self) -> None:
|
||||
self.stop_global_capturing()
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ from _pytest.warning_types import PytestConfigWarning
|
|||
if TYPE_CHECKING:
|
||||
from typing import Type
|
||||
|
||||
from _pytest._code.code import _TracebackStyle
|
||||
from .argparsing import Argument
|
||||
|
||||
|
||||
|
@ -893,9 +894,13 @@ class Config:
|
|||
|
||||
return self
|
||||
|
||||
def notify_exception(self, excinfo, option=None):
|
||||
def notify_exception(
|
||||
self,
|
||||
excinfo: ExceptionInfo[BaseException],
|
||||
option: Optional[argparse.Namespace] = None,
|
||||
) -> None:
|
||||
if option and getattr(option, "fulltrace", False):
|
||||
style = "long"
|
||||
style = "long" # type: _TracebackStyle
|
||||
else:
|
||||
style = "native"
|
||||
excrepr = excinfo.getrepr(
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
import argparse
|
||||
import functools
|
||||
import sys
|
||||
import types
|
||||
from typing import Generator
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
from _pytest import outcomes
|
||||
from _pytest._code import ExceptionInfo
|
||||
from _pytest.compat import TYPE_CHECKING
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ConftestImportFailure
|
||||
|
@ -280,9 +282,10 @@ class PdbInvoke:
|
|||
out, err = capman.read_global_capture()
|
||||
sys.stdout.write(out)
|
||||
sys.stdout.write(err)
|
||||
assert call.excinfo is not None
|
||||
_enter_pdb(node, call.excinfo, report)
|
||||
|
||||
def pytest_internalerror(self, excrepr, excinfo) -> None:
|
||||
def pytest_internalerror(self, excinfo: ExceptionInfo[BaseException]) -> None:
|
||||
tb = _postmortem_traceback(excinfo)
|
||||
post_mortem(tb)
|
||||
|
||||
|
@ -320,7 +323,9 @@ def maybe_wrap_pytest_function_for_tracing(pyfuncitem):
|
|||
wrap_pytest_function_for_tracing(pyfuncitem)
|
||||
|
||||
|
||||
def _enter_pdb(node: Node, excinfo, rep: BaseReport) -> BaseReport:
|
||||
def _enter_pdb(
|
||||
node: Node, excinfo: ExceptionInfo[BaseException], rep: BaseReport
|
||||
) -> BaseReport:
|
||||
# XXX we re-use the TerminalReporter's terminalwriter
|
||||
# because this seems to avoid some encoding related troubles
|
||||
# for not completely clear reasons.
|
||||
|
@ -349,7 +354,7 @@ def _enter_pdb(node: Node, excinfo, rep: BaseReport) -> BaseReport:
|
|||
return rep
|
||||
|
||||
|
||||
def _postmortem_traceback(excinfo):
|
||||
def _postmortem_traceback(excinfo: ExceptionInfo[BaseException]) -> types.TracebackType:
|
||||
from doctest import UnexpectedException
|
||||
|
||||
if isinstance(excinfo.value, UnexpectedException):
|
||||
|
@ -361,10 +366,11 @@ def _postmortem_traceback(excinfo):
|
|||
# Use the underlying exception instead:
|
||||
return excinfo.value.excinfo[2]
|
||||
else:
|
||||
assert excinfo._excinfo is not None
|
||||
return excinfo._excinfo[2]
|
||||
|
||||
|
||||
def post_mortem(t) -> None:
|
||||
def post_mortem(t: types.TracebackType) -> None:
|
||||
p = pytestPDB._init_pdb("post_mortem")
|
||||
p.reset()
|
||||
p.interaction(None, t)
|
||||
|
|
|
@ -19,6 +19,7 @@ if TYPE_CHECKING:
|
|||
import warnings
|
||||
from typing_extensions import Literal
|
||||
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
from _pytest.code import ExceptionInfo
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
|
@ -759,8 +760,14 @@ def pytest_doctest_prepare_content(content):
|
|||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
def pytest_internalerror(excrepr, excinfo):
|
||||
""" called for internal errors. """
|
||||
def pytest_internalerror(
|
||||
excrepr: "ExceptionRepr", excinfo: "ExceptionInfo[BaseException]",
|
||||
) -> Optional[bool]:
|
||||
"""Called for internal errors.
|
||||
|
||||
Return True to suppress the fallback handling of printing an
|
||||
INTERNALERROR message directly to sys.stderr.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_keyboard_interrupt(
|
||||
|
|
|
@ -26,6 +26,7 @@ import pytest
|
|||
from _pytest import deprecated
|
||||
from _pytest import nodes
|
||||
from _pytest import timing
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
from _pytest.compat import TYPE_CHECKING
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import filename_arg
|
||||
|
@ -642,7 +643,7 @@ class LogXML:
|
|||
else:
|
||||
reporter.append_collect_skipped(report)
|
||||
|
||||
def pytest_internalerror(self, excrepr) -> None:
|
||||
def pytest_internalerror(self, excrepr: ExceptionRepr) -> None:
|
||||
reporter = self.node_reporter("internal")
|
||||
reporter.attrs.update(classname="pytest", name="internal")
|
||||
reporter._add_simple(Junit.error, "internal error", excrepr)
|
||||
|
|
|
@ -5,6 +5,7 @@ import os
|
|||
|
||||
import py
|
||||
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
from _pytest.config import Config
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.reports import CollectReport
|
||||
|
@ -99,9 +100,9 @@ class ResultLog:
|
|||
longrepr = "%s:%d: %s" % report.longrepr # type: ignore
|
||||
self.log_outcome(report, code, longrepr)
|
||||
|
||||
def pytest_internalerror(self, excrepr):
|
||||
reprcrash = getattr(excrepr, "reprcrash", None)
|
||||
path = getattr(reprcrash, "path", None)
|
||||
if path is None:
|
||||
def pytest_internalerror(self, excrepr: ExceptionRepr) -> None:
|
||||
if excrepr.reprcrash is not None:
|
||||
path = excrepr.reprcrash.path
|
||||
else:
|
||||
path = "cwd:%s" % py.path.local()
|
||||
self.write_log_entry(path, "!", str(excrepr))
|
||||
|
|
|
@ -31,8 +31,7 @@ import pytest
|
|||
from _pytest import nodes
|
||||
from _pytest import timing
|
||||
from _pytest._code import ExceptionInfo
|
||||
from _pytest._code.code import ExceptionChainRepr
|
||||
from _pytest._code.code import ReprExceptionInfo
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest._io.wcwidth import wcswidth
|
||||
from _pytest.compat import order_preserving_dict
|
||||
|
@ -318,9 +317,7 @@ class TerminalReporter:
|
|||
self._show_progress_info = self._determine_show_progress_info()
|
||||
self._collect_report_last_write = None # type: Optional[float]
|
||||
self._already_displayed_warnings = None # type: Optional[int]
|
||||
self._keyboardinterrupt_memo = (
|
||||
None
|
||||
) # type: Optional[Union[ReprExceptionInfo, ExceptionChainRepr]]
|
||||
self._keyboardinterrupt_memo = None # type: Optional[ExceptionRepr]
|
||||
|
||||
@property
|
||||
def writer(self) -> TerminalWriter:
|
||||
|
@ -454,10 +451,10 @@ class TerminalReporter:
|
|||
if set_main_color:
|
||||
self._set_main_color()
|
||||
|
||||
def pytest_internalerror(self, excrepr):
|
||||
def pytest_internalerror(self, excrepr: ExceptionRepr) -> bool:
|
||||
for line in str(excrepr).split("\n"):
|
||||
self.write_line("INTERNALERROR> " + line)
|
||||
return 1
|
||||
return True
|
||||
|
||||
def pytest_warning_recorded(
|
||||
self, warning_message: warnings.WarningMessage, nodeid: str,
|
||||
|
|
Loading…
Reference in New Issue