summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2020-05-01 14:40:17 +0300
committerRan Benita <ran@unusedvar.com>2020-06-05 11:34:20 +0300
commit2b05faff0a0172dbc74b81f47528e56ad608839e (patch)
tree9dd289ab7c1fc9ba2b361ce6528ba053bf8c0a95 /src
parent54ad048be7182018e70479bd3d9b88bcb6376c00 (diff)
downloadpytest-2b05faff0a0172dbc74b81f47528e56ad608839e.tar.gz
Improve types around repr_failure()
Diffstat (limited to 'src')
-rw-r--r--src/_pytest/_code/code.py2
-rw-r--r--src/_pytest/doctest.py5
-rw-r--r--src/_pytest/nodes.py24
-rw-r--r--src/_pytest/python.py6
-rw-r--r--src/_pytest/runner.py6
-rw-r--r--src/_pytest/skipping.py3
6 files changed, 31 insertions, 15 deletions
diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py
index 09b2c1af5..a40b23470 100644
--- a/src/_pytest/_code/code.py
+++ b/src/_pytest/_code/code.py
@@ -47,7 +47,7 @@ if TYPE_CHECKING:
from typing_extensions import Literal
from weakref import ReferenceType
- _TracebackStyle = Literal["long", "short", "line", "no", "native", "value"]
+ _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
class Code:
diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py
index ab8085982..7aaacb481 100644
--- a/src/_pytest/doctest.py
+++ b/src/_pytest/doctest.py
@@ -300,7 +300,10 @@ class DoctestItem(pytest.Item):
sys.stdout.write(out)
sys.stderr.write(err)
- def repr_failure(self, excinfo):
+ # TODO: Type ignored -- breaks Liskov Substitution.
+ def repr_failure( # type: ignore[override] # noqa: F821
+ self, excinfo: ExceptionInfo[BaseException],
+ ) -> Union[str, TerminalRepr]:
import doctest
failures = (
diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py
index 15f91343f..3757e0b27 100644
--- a/src/_pytest/nodes.py
+++ b/src/_pytest/nodes.py
@@ -17,9 +17,8 @@ import py
import _pytest._code
from _pytest._code import getfslineno
-from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ExceptionInfo
-from _pytest._code.code import ReprExceptionInfo
+from _pytest._code.code import TerminalRepr
from _pytest.compat import cached_property
from _pytest.compat import overload
from _pytest.compat import TYPE_CHECKING
@@ -29,7 +28,6 @@ from _pytest.config import PytestPluginManager
from _pytest.deprecated import NODE_USE_FROM_PARENT
from _pytest.fixtures import FixtureDef
from _pytest.fixtures import FixtureLookupError
-from _pytest.fixtures import FixtureLookupErrorRepr
from _pytest.mark.structures import Mark
from _pytest.mark.structures import MarkDecorator
from _pytest.mark.structures import NodeKeywords
@@ -43,6 +41,7 @@ if TYPE_CHECKING:
# Imported here due to circular import.
from _pytest.main import Session
from _pytest.warning_types import PytestWarning
+ from _pytest._code.code import _TracebackStyle
SEP = "/"
@@ -355,8 +354,10 @@ class Node(metaclass=NodeMeta):
pass
def _repr_failure_py(
- self, excinfo: ExceptionInfo[BaseException], style=None,
- ) -> Union[str, ReprExceptionInfo, ExceptionChainRepr, FixtureLookupErrorRepr]:
+ self,
+ excinfo: ExceptionInfo[BaseException],
+ style: "Optional[_TracebackStyle]" = None,
+ ) -> TerminalRepr:
if isinstance(excinfo.value, ConftestImportFailure):
excinfo = ExceptionInfo(excinfo.value.excinfo)
if isinstance(excinfo.value, fail.Exception):
@@ -406,8 +407,10 @@ class Node(metaclass=NodeMeta):
)
def repr_failure(
- self, excinfo, style=None
- ) -> Union[str, ReprExceptionInfo, ExceptionChainRepr, FixtureLookupErrorRepr]:
+ self,
+ excinfo: ExceptionInfo[BaseException],
+ style: "Optional[_TracebackStyle]" = None,
+ ) -> Union[str, TerminalRepr]:
"""
Return a representation of a collection or test failure.
@@ -453,13 +456,16 @@ class Collector(Node):
"""
raise NotImplementedError("abstract")
- def repr_failure(self, excinfo):
+ # TODO: This omits the style= parameter which breaks Liskov Substitution.
+ def repr_failure( # type: ignore[override] # noqa: F821
+ self, excinfo: ExceptionInfo[BaseException]
+ ) -> Union[str, TerminalRepr]:
"""
Return a representation of a collection failure.
:param excinfo: Exception information for the failure.
"""
- if excinfo.errisinstance(self.CollectError) and not self.config.getoption(
+ if isinstance(excinfo.value, self.CollectError) and not self.config.getoption(
"fulltrace", False
):
exc = excinfo.value
diff --git a/src/_pytest/python.py b/src/_pytest/python.py
index 41dd8b292..4b716c616 100644
--- a/src/_pytest/python.py
+++ b/src/_pytest/python.py
@@ -60,6 +60,7 @@ from _pytest.mark.structures import normalize_mark_list
from _pytest.outcomes import fail
from _pytest.outcomes import skip
from _pytest.pathlib import parts
+from _pytest.reports import TerminalRepr
from _pytest.warning_types import PytestCollectionWarning
from _pytest.warning_types import PytestUnhandledCoroutineWarning
@@ -1591,7 +1592,10 @@ class Function(PyobjMixin, nodes.Item):
for entry in excinfo.traceback[1:-1]:
entry.set_repr_style("short")
- def repr_failure(self, excinfo, outerr=None):
+ # TODO: Type ignored -- breaks Liskov Substitution.
+ def repr_failure( # type: ignore[override] # noqa: F821
+ self, excinfo: ExceptionInfo[BaseException], outerr: None = None
+ ) -> Union[str, TerminalRepr]:
assert outerr is None, "XXX outerr usage is deprecated"
style = self.config.getoption("tbstyle", "auto")
if style == "auto":
diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py
index f89b67399..3ca8d7ea4 100644
--- a/src/_pytest/runner.py
+++ b/src/_pytest/runner.py
@@ -2,6 +2,7 @@
import bdb
import os
import sys
+from typing import Any
from typing import Callable
from typing import cast
from typing import Dict
@@ -256,7 +257,7 @@ class CallInfo(Generic[_T]):
"""
_result = attr.ib(type="Optional[_T]")
- excinfo = attr.ib(type=Optional[ExceptionInfo])
+ excinfo = attr.ib(type=Optional[ExceptionInfo[BaseException]])
start = attr.ib(type=float)
stop = attr.ib(type=float)
duration = attr.ib(type=float)
@@ -313,7 +314,8 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport:
def pytest_make_collect_report(collector: Collector) -> CollectReport:
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
- longrepr = None
+ # TODO: Better typing for longrepr.
+ longrepr = None # type: Optional[Any]
if not call.excinfo:
outcome = "passed" # type: Literal["passed", "skipped", "failed"]
else:
diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py
index 54621f111..bbd4593fd 100644
--- a/src/_pytest/skipping.py
+++ b/src/_pytest/skipping.py
@@ -148,7 +148,8 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]):
elif item.config.option.runxfail:
pass # don't interfere
- elif call.excinfo and call.excinfo.errisinstance(xfail.Exception):
+ elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception):
+ assert call.excinfo.value.msg is not None
rep.wasxfail = "reason: " + call.excinfo.value.msg
rep.outcome = "skipped"
elif evalxfail and not rep.skipped and evalxfail.wasvalid() and evalxfail.istrue():