diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index dc018ce2a..698616664 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -17,7 +17,6 @@ from functools import lru_cache from pathlib import Path from textwrap import dedent from types import FunctionType -from types import TracebackType from typing import Any from typing import Callable from typing import cast @@ -112,16 +111,14 @@ class ConftestImportFailure(Exception): def __init__( self, path: Path, - excinfo: Tuple[Type[Exception], Exception, TracebackType], + *, + cause: Exception, ) -> None: - super().__init__(path, excinfo) self.path = path - self.excinfo = excinfo + self.cause = cause def __str__(self) -> str: - return "{}: {} (from {})".format( - self.excinfo[0].__name__, self.excinfo[1], self.path - ) + return f"{type(self.cause).__name__}: {self.cause} (from {self.path})" def filter_traceback_for_conftest_import_failure( @@ -152,7 +149,7 @@ def main( try: config = _prepareconfig(args, plugins) except ConftestImportFailure as e: - exc_info = ExceptionInfo.from_exc_info(e.excinfo) + exc_info = ExceptionInfo.from_exception(e.cause) tw = TerminalWriter(sys.stderr) tw.line(f"ImportError while loading conftest '{e.path}'.", red=True) exc_info.traceback = exc_info.traceback.filter( @@ -654,8 +651,7 @@ class PytestPluginManager(PluginManager): mod = import_path(conftestpath, mode=importmode, root=rootpath) except Exception as e: assert e.__traceback__ is not None - exc_info = (type(e), e, e.__traceback__) - raise ConftestImportFailure(conftestpath, exc_info) from e + raise ConftestImportFailure(conftestpath, cause=e) from e self._check_non_top_pytest_plugins(mod, conftestpath) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 69ec58c5b..57f26d219 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -377,7 +377,8 @@ def _postmortem_traceback(excinfo: ExceptionInfo[BaseException]) -> types.Traceb elif isinstance(excinfo.value, ConftestImportFailure): # A config.ConftestImportFailure is not useful for post_mortem. # Use the underlying exception instead: - return excinfo.value.excinfo[2] + assert excinfo.value.cause.__traceback__ is not None + return excinfo.value.cause.__traceback__ else: assert excinfo._excinfo is not None return excinfo._excinfo[2] diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 3f22b5871..45bbb4b57 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -384,7 +384,7 @@ class Node(abc.ABC, metaclass=NodeMeta): from _pytest.fixtures import FixtureLookupError if isinstance(excinfo.value, ConftestImportFailure): - excinfo = ExceptionInfo.from_exc_info(excinfo.value.excinfo) + excinfo = ExceptionInfo.from_exception(excinfo.value.cause) if isinstance(excinfo.value, fail.Exception): if not excinfo.value.pytrace: style = "value" diff --git a/testing/test_config.py b/testing/test_config.py index 2d95fb4cc..0f586c043 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2108,9 +2108,7 @@ def test_conftest_import_error_repr(tmp_path: Path) -> None: try: raise RuntimeError("some error") except Exception as exc: - assert exc.__traceback__ is not None - exc_info = (type(exc), exc, exc.__traceback__) - raise ConftestImportFailure(path, exc_info) from exc + raise ConftestImportFailure(path, cause=exc) from exc def test_strtobool() -> None: