From fb2640b82fdf6789d36a8204066695c2cc14ff6a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Jun 2020 18:34:32 +0300 Subject: [PATCH] Stop using ExceptionInfo.errisinstance internally It does the same as a simple isinstance check, but adds a little layer of obscurity on top, which the type checker can't penetrate. --- src/_pytest/_code/code.py | 7 +++++-- src/_pytest/main.py | 2 +- src/_pytest/reports.py | 2 +- src/_pytest/runner.py | 21 ++++++++++++++------- src/_pytest/unittest.py | 4 +--- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index e548bceb7..ab38b204f 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -558,7 +558,10 @@ class ExceptionInfo(Generic[_E]): def errisinstance( self, exc: Union["Type[BaseException]", Tuple["Type[BaseException]", ...]] ) -> bool: - """ return True if the exception is an instance of exc """ + """Return True if the exception is an instance of exc. + + Consider using ``isinstance(excinfo.value, exc)`` instead. + """ return isinstance(self.value, exc) def _getreprcrash(self) -> "ReprFileLocation": @@ -804,7 +807,7 @@ class FormattedExcinfo: if self.tbfilter: traceback = traceback.filter() - if excinfo.errisinstance(RecursionError): + if isinstance(excinfo.value, RecursionError): traceback, extraline = self._truncate_recursive_traceback(traceback) else: extraline = None diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 98dabaf87..7e6816506 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -265,7 +265,7 @@ def wrap_session( session.exitstatus = exc.returncode sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc)) else: - if excinfo.errisinstance(SystemExit): + if isinstance(excinfo.value, SystemExit): sys.stderr.write("mainloop: caught unexpected SystemExit!\n") finally: diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 7aba0b024..186c53ed3 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -308,7 +308,7 @@ class TestReport(BaseReport): if not isinstance(excinfo, ExceptionInfo): outcome = "failed" longrepr = excinfo - elif excinfo.errisinstance(skip.Exception): + elif isinstance(excinfo.value, skip.Exception): outcome = "skipped" r = excinfo._getreprcrash() longrepr = (str(r.path), r.lineno, r.message) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 8b23cb49e..702380a5b 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -215,11 +215,18 @@ def call_and_report( def check_interactive_exception(call: "CallInfo", report: BaseReport) -> bool: - return call.excinfo is not None and not ( - hasattr(report, "wasxfail") - or call.excinfo.errisinstance(Skipped) - or call.excinfo.errisinstance(bdb.BdbQuit) - ) + """Check whether the call raised an exception that should be reported as + interactive.""" + if call.excinfo is None: + # Didn't raise. + return False + if hasattr(report, "wasxfail"): + # Exception was expected. + return False + if isinstance(call.excinfo.value, (Skipped, bdb.BdbQuit)): + # Special control flow exception. + return False + return True def call_runtest_hook( @@ -287,7 +294,7 @@ class CallInfo(Generic[_T]): result = func() # type: Optional[_T] except BaseException: excinfo = ExceptionInfo.from_current() - if reraise is not None and excinfo.errisinstance(reraise): + if reraise is not None and isinstance(excinfo.value, reraise): raise result = None # use the perf counter @@ -325,7 +332,7 @@ def pytest_make_collect_report(collector: Collector) -> CollectReport: if unittest is not None: # Type ignored because unittest is loaded dynamically. skip_exceptions.append(unittest.SkipTest) # type: ignore - if call.excinfo.errisinstance(tuple(skip_exceptions)): + if isinstance(call.excinfo.value, tuple(skip_exceptions)): outcome = "skipped" r_ = collector._repr_failure_py(call.excinfo, "line") assert isinstance(r_, ExceptionChainRepr), repr(r_) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 0e4a31311..bd61726c7 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -302,9 +302,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: if ( unittest and call.excinfo - and call.excinfo.errisinstance( - unittest.SkipTest # type: ignore[attr-defined] # noqa: F821 - ) + and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined] ): excinfo = call.excinfo # let's substitute the excinfo with a pytest.skip one