Merge pull request #8218 from bluetech/reports2

Misc small code improvements
This commit is contained in:
Ran Benita 2021-01-04 22:47:32 +02:00 committed by GitHub
commit 5336ba28cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 32 deletions

View File

@ -16,6 +16,7 @@ from typing import Generic
from typing import Iterable
from typing import Iterator
from typing import List
from typing import MutableMapping
from typing import Optional
from typing import overload
from typing import Sequence
@ -525,9 +526,10 @@ class FixtureRequest:
return self._pyfuncitem.fspath # type: ignore
@property
def keywords(self):
def keywords(self) -> MutableMapping[str, Any]:
"""Keywords/markers dictionary for the underlying node."""
return self.node.keywords
node: nodes.Node = self.node
return node.keywords
@property
def session(self) -> "Session":
@ -607,14 +609,11 @@ class FixtureRequest:
def _get_fixturestack(self) -> List["FixtureDef[Any]"]:
current = self
values: List[FixtureDef[Any]] = []
while 1:
fixturedef = getattr(current, "_fixturedef", None)
if fixturedef is None:
values.reverse()
return values
values.append(fixturedef)
assert isinstance(current, SubRequest)
while isinstance(current, SubRequest):
values.append(current._fixturedef) # type: ignore[has-type]
current = current._parent_request
values.reverse()
return values
def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None:
"""Create a SubRequest based on "self" and call the execute method

View File

@ -2,11 +2,12 @@
from _pytest import python
from _pytest import unittest
from _pytest.config import hookimpl
from _pytest.fixtures import getfixturemarker
from _pytest.nodes import Item
@hookimpl(trylast=True)
def pytest_runtest_setup(item):
def pytest_runtest_setup(item) -> None:
if is_potential_nosetest(item):
if not call_optional(item.obj, "setup"):
# Call module level setup if there is no object level one.
@ -15,7 +16,7 @@ def pytest_runtest_setup(item):
item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)
def teardown_nose(item):
def teardown_nose(item) -> None:
if is_potential_nosetest(item):
if not call_optional(item.obj, "teardown"):
call_optional(item.parent.obj, "teardown")
@ -29,11 +30,16 @@ def is_potential_nosetest(item: Item) -> bool:
)
def call_optional(obj, name):
def call_optional(obj: object, name: str) -> bool:
method = getattr(obj, name, None)
isfixture = hasattr(method, "_pytestfixturefunction")
if method is not None and not isfixture and callable(method):
# If there's any problems allow the exception to raise rather than
# silently ignoring them.
method()
return True
if method is None:
return False
is_fixture = getfixturemarker(method) is not None
if is_fixture:
return False
if not callable(method):
return False
# If there are any problems allow the exception to raise rather than
# silently ignoring it.
method()
return True

View File

@ -922,10 +922,6 @@ class CallSpec2:
cs._idlist = list(self._idlist)
return cs
def _checkargnotcontained(self, arg: str) -> None:
if arg in self.params or arg in self.funcargs:
raise ValueError(f"duplicate {arg!r}")
def getparam(self, name: str) -> object:
try:
return self.params[name]
@ -947,7 +943,8 @@ class CallSpec2:
param_index: int,
) -> None:
for arg, val in zip(argnames, valset):
self._checkargnotcontained(arg)
if arg in self.params or arg in self.funcargs:
raise ValueError(f"duplicate {arg!r}")
valtype_for_arg = valtypes[arg]
if valtype_for_arg == "params":
self.params[arg] = val

View File

@ -65,6 +65,7 @@ class BaseReport:
]
sections: List[Tuple[str, str]]
nodeid: str
outcome: "Literal['passed', 'failed', 'skipped']"
def __init__(self, **kw: Any) -> None:
self.__dict__.update(kw)
@ -141,9 +142,17 @@ class BaseReport:
content for (prefix, content) in self.get_sections("Captured stderr")
)
passed = property(lambda x: x.outcome == "passed")
failed = property(lambda x: x.outcome == "failed")
skipped = property(lambda x: x.outcome == "skipped")
@property
def passed(self) -> bool:
return self.outcome == "passed"
@property
def failed(self) -> bool:
return self.outcome == "failed"
@property
def skipped(self) -> bool:
return self.outcome == "skipped"
@property
def fspath(self) -> str:
@ -348,8 +357,10 @@ class CollectReport(BaseReport):
def __init__(
self,
nodeid: str,
outcome: "Literal['passed', 'skipped', 'failed']",
longrepr,
outcome: "Literal['passed', 'failed', 'skipped']",
longrepr: Union[
None, ExceptionInfo[BaseException], Tuple[str, int, str], str, TerminalRepr
],
result: Optional[List[Union[Item, Collector]]],
sections: Iterable[Tuple[str, str]] = (),
**extra,

View File

@ -3,6 +3,7 @@ from typing import Any
import pytest
from _pytest import runner
from _pytest._code import getfslineno
from _pytest.fixtures import getfixturemarker
from _pytest.pytester import Pytester
@ -334,7 +335,8 @@ class TestReRunTests:
def test_pytestconfig_is_session_scoped() -> None:
from _pytest.fixtures import pytestconfig
marker = pytestconfig._pytestfixturefunction # type: ignore
marker = getfixturemarker(pytestconfig)
assert marker is not None
assert marker.scope == "session"

View File

@ -2230,19 +2230,19 @@ def test_skip_reasons_folding() -> None:
ev1 = cast(CollectReport, X())
ev1.when = "execute"
ev1.skipped = True
ev1.skipped = True # type: ignore[misc]
ev1.longrepr = longrepr
ev2 = cast(CollectReport, X())
ev2.when = "execute"
ev2.longrepr = longrepr
ev2.skipped = True
ev2.skipped = True # type: ignore[misc]
# ev3 might be a collection report
ev3 = cast(CollectReport, X())
ev3.when = "collect"
ev3.longrepr = longrepr
ev3.skipped = True
ev3.skipped = True # type: ignore[misc]
values = _folded_skips(Path.cwd(), [ev1, ev2, ev3])
assert len(values) == 1