Allow creating ExceptionInfo from existing exc_info for better typing
This way the ExceptionInfo generic parameter can be inferred from the passed-in exc_info. See for example the replaced cast().
This commit is contained in:
parent
3f1fb62584
commit
11f1f79222
|
@ -396,6 +396,33 @@ class ExceptionInfo(Generic[_E]):
|
||||||
_striptext = attr.ib(type=str, default="")
|
_striptext = attr.ib(type=str, default="")
|
||||||
_traceback = attr.ib(type=Optional[Traceback], default=None)
|
_traceback = attr.ib(type=Optional[Traceback], default=None)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_exc_info(
|
||||||
|
cls,
|
||||||
|
exc_info: Tuple["Type[_E]", "_E", TracebackType],
|
||||||
|
exprinfo: Optional[str] = None,
|
||||||
|
) -> "ExceptionInfo[_E]":
|
||||||
|
"""returns an ExceptionInfo for an existing exc_info tuple.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Experimental API
|
||||||
|
|
||||||
|
|
||||||
|
:param exprinfo: a text string helping to determine if we should
|
||||||
|
strip ``AssertionError`` from the output, defaults
|
||||||
|
to the exception message/``__str__()``
|
||||||
|
"""
|
||||||
|
_striptext = ""
|
||||||
|
if exprinfo is None and isinstance(exc_info[1], AssertionError):
|
||||||
|
exprinfo = getattr(exc_info[1], "msg", None)
|
||||||
|
if exprinfo is None:
|
||||||
|
exprinfo = saferepr(exc_info[1])
|
||||||
|
if exprinfo and exprinfo.startswith(cls._assert_start_repr):
|
||||||
|
_striptext = "AssertionError: "
|
||||||
|
|
||||||
|
return cls(exc_info, _striptext)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_current(
|
def from_current(
|
||||||
cls, exprinfo: Optional[str] = None
|
cls, exprinfo: Optional[str] = None
|
||||||
|
@ -411,20 +438,12 @@ class ExceptionInfo(Generic[_E]):
|
||||||
strip ``AssertionError`` from the output, defaults
|
strip ``AssertionError`` from the output, defaults
|
||||||
to the exception message/``__str__()``
|
to the exception message/``__str__()``
|
||||||
"""
|
"""
|
||||||
tup_ = sys.exc_info()
|
tup = sys.exc_info()
|
||||||
assert tup_[0] is not None, "no current exception"
|
assert tup[0] is not None, "no current exception"
|
||||||
assert tup_[1] is not None, "no current exception"
|
assert tup[1] is not None, "no current exception"
|
||||||
assert tup_[2] is not None, "no current exception"
|
assert tup[2] is not None, "no current exception"
|
||||||
tup = (tup_[0], tup_[1], tup_[2])
|
exc_info = (tup[0], tup[1], tup[2])
|
||||||
_striptext = ""
|
return cls.from_exc_info(exc_info)
|
||||||
if exprinfo is None and isinstance(tup[1], AssertionError):
|
|
||||||
exprinfo = getattr(tup[1], "msg", None)
|
|
||||||
if exprinfo is None:
|
|
||||||
exprinfo = saferepr(tup[1])
|
|
||||||
if exprinfo and exprinfo.startswith(cls._assert_start_repr):
|
|
||||||
_striptext = "AssertionError: "
|
|
||||||
|
|
||||||
return cls(tup, _striptext)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def for_later(cls) -> "ExceptionInfo[_E]":
|
def for_later(cls) -> "ExceptionInfo[_E]":
|
||||||
|
|
|
@ -707,11 +707,11 @@ def raises(
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
func(*args[1:], **kwargs)
|
func(*args[1:], **kwargs)
|
||||||
except expected_exception:
|
except expected_exception as e:
|
||||||
# Cast to narrow the type to expected_exception (_E).
|
# We just caught the exception - there is a traceback.
|
||||||
return cast(
|
assert e.__traceback__ is not None
|
||||||
_pytest._code.ExceptionInfo[_E],
|
return _pytest._code.ExceptionInfo.from_exc_info(
|
||||||
_pytest._code.ExceptionInfo.from_current(),
|
(type(e), e, e.__traceback__)
|
||||||
)
|
)
|
||||||
fail(message)
|
fail(message)
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class TWMock:
|
||||||
fullwidth = 80
|
fullwidth = 80
|
||||||
|
|
||||||
|
|
||||||
def test_excinfo_simple():
|
def test_excinfo_simple() -> None:
|
||||||
try:
|
try:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -66,6 +66,14 @@ def test_excinfo_simple():
|
||||||
assert info.type == ValueError
|
assert info.type == ValueError
|
||||||
|
|
||||||
|
|
||||||
|
def test_excinfo_from_exc_info_simple():
|
||||||
|
try:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError as e:
|
||||||
|
info = _pytest._code.ExceptionInfo.from_exc_info((type(e), e, e.__traceback__))
|
||||||
|
assert info.type == ValueError
|
||||||
|
|
||||||
|
|
||||||
def test_excinfo_getstatement():
|
def test_excinfo_getstatement():
|
||||||
def g():
|
def g():
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
Loading…
Reference in New Issue