From 7081ed19b892a799e1dea99a7922cab79fefc1df Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 7 Jun 2020 13:05:32 +0300 Subject: [PATCH] hookspec: type annotate pytest_keyboard_interrupt --- src/_pytest/capture.py | 2 +- src/_pytest/hookspec.py | 6 +++++- src/_pytest/terminal.py | 14 +++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 6009e1f67..f2beb8d8d 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -749,7 +749,7 @@ class CaptureManager: yield @pytest.hookimpl(tryfirst=True) - def pytest_keyboard_interrupt(self, excinfo): + def pytest_keyboard_interrupt(self) -> None: self.stop_global_capturing() @pytest.hookimpl(tryfirst=True) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 18a9fb39a..a6decb03a 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -19,6 +19,7 @@ if TYPE_CHECKING: import warnings from typing_extensions import Literal + from _pytest.code import ExceptionInfo from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import PytestPluginManager @@ -30,6 +31,7 @@ if TYPE_CHECKING: from _pytest.nodes import Collector from _pytest.nodes import Item from _pytest.nodes import Node + from _pytest.outcomes import Exit from _pytest.python import Function from _pytest.python import Metafunc from _pytest.python import Module @@ -761,7 +763,9 @@ def pytest_internalerror(excrepr, excinfo): """ called for internal errors. """ -def pytest_keyboard_interrupt(excinfo): +def pytest_keyboard_interrupt( + excinfo: "ExceptionInfo[Union[KeyboardInterrupt, Exit]]", +) -> None: """ called for keyboard interrupt. """ diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 9c2665fb8..da8c5fc9e 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -30,6 +30,9 @@ from more_itertools import collapse 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._io import TerminalWriter from _pytest._io.wcwidth import wcswidth from _pytest.compat import order_preserving_dict @@ -315,6 +318,9 @@ 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]] @property def writer(self) -> TerminalWriter: @@ -783,7 +789,7 @@ class TerminalReporter: self.write_sep("!", str(session.shouldfail), red=True) if exitstatus == ExitCode.INTERRUPTED: self._report_keyboardinterrupt() - del self._keyboardinterrupt_memo + self._keyboardinterrupt_memo = None elif session.shouldstop: self.write_sep("!", str(session.shouldstop), red=True) self.summary_stats() @@ -799,15 +805,17 @@ class TerminalReporter: # Display any extra warnings from teardown here (if any). self.summary_warnings() - def pytest_keyboard_interrupt(self, excinfo) -> None: + def pytest_keyboard_interrupt(self, excinfo: ExceptionInfo[BaseException]) -> None: self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) def pytest_unconfigure(self) -> None: - if hasattr(self, "_keyboardinterrupt_memo"): + if self._keyboardinterrupt_memo is not None: self._report_keyboardinterrupt() def _report_keyboardinterrupt(self) -> None: excrepr = self._keyboardinterrupt_memo + assert excrepr is not None + assert excrepr.reprcrash is not None msg = excrepr.reprcrash.message self.write_sep("!", msg) if "KeyboardInterrupt" in msg: