Stop using more-itertools
We barely use it; the couple places that do are not really worth the extra dependency, I think the code is clearer without it. Also simplifies one (regular) itertools usage. Also improves a check and an error message in `pytest.raises`.
This commit is contained in:
parent
645cbc91fc
commit
96a48f0c66
|
@ -0,0 +1 @@
|
|||
The dependency on the ``more-itertools`` package has been removed.
|
|
@ -42,7 +42,6 @@ packages =
|
|||
install_requires =
|
||||
attrs>=17.4.0
|
||||
iniconfig
|
||||
more-itertools>=4.0.0
|
||||
packaging
|
||||
pluggy>=0.12,<1.0
|
||||
py>=1.8.2
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import functools
|
||||
import inspect
|
||||
import itertools
|
||||
import sys
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
|
@ -1489,10 +1488,10 @@ class FixtureManager:
|
|||
else:
|
||||
argnames = ()
|
||||
|
||||
usefixtures = itertools.chain.from_iterable(
|
||||
mark.args for mark in node.iter_markers(name="usefixtures")
|
||||
usefixtures = tuple(
|
||||
arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args
|
||||
)
|
||||
initialnames = tuple(usefixtures) + argnames
|
||||
initialnames = usefixtures + argnames
|
||||
fm = node.session._fixturemanager
|
||||
initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure(
|
||||
initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import inspect
|
||||
import math
|
||||
import pprint
|
||||
from collections.abc import Iterable
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Sized
|
||||
from decimal import Decimal
|
||||
from itertools import filterfalse
|
||||
from numbers import Number
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
|
@ -18,8 +16,6 @@ from typing import Tuple
|
|||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
from more_itertools.more import always_iterable
|
||||
|
||||
import _pytest._code
|
||||
from _pytest.compat import overload
|
||||
from _pytest.compat import STRING_TYPES
|
||||
|
@ -30,9 +26,6 @@ if TYPE_CHECKING:
|
|||
from typing import Type
|
||||
|
||||
|
||||
BASE_TYPE = (type, STRING_TYPES)
|
||||
|
||||
|
||||
def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
|
||||
at_str = " at {}".format(at) if at else ""
|
||||
return TypeError(
|
||||
|
@ -680,11 +673,16 @@ def raises( # noqa: F811
|
|||
documentation for :ref:`the try statement <python:try>`.
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
for exc in filterfalse(
|
||||
inspect.isclass, always_iterable(expected_exception, BASE_TYPE)
|
||||
):
|
||||
msg = "exceptions must be derived from BaseException, not %s"
|
||||
raise TypeError(msg % type(exc))
|
||||
|
||||
if isinstance(expected_exception, type):
|
||||
excepted_exceptions = (expected_exception,) # type: Tuple[Type[_E], ...]
|
||||
else:
|
||||
excepted_exceptions = expected_exception
|
||||
for exc in excepted_exceptions:
|
||||
if not isinstance(exc, type) or not issubclass(exc, BaseException):
|
||||
msg = "expected exception must be a BaseException type, not {}"
|
||||
not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__
|
||||
raise TypeError(msg.format(not_a))
|
||||
|
||||
message = "DID NOT RAISE {}".format(expected_exception)
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ from typing import Union
|
|||
import attr
|
||||
import pluggy
|
||||
import py
|
||||
from more_itertools import collapse
|
||||
|
||||
import pytest
|
||||
from _pytest import nodes
|
||||
|
@ -715,11 +714,14 @@ class TerminalReporter:
|
|||
self._write_report_lines_from_hooks(lines)
|
||||
|
||||
def _write_report_lines_from_hooks(
|
||||
self, lines: List[Union[str, List[str]]]
|
||||
self, lines: Sequence[Union[str, Sequence[str]]]
|
||||
) -> None:
|
||||
lines.reverse()
|
||||
for line in collapse(lines):
|
||||
self.write_line(line)
|
||||
for line_or_lines in reversed(lines):
|
||||
if isinstance(line_or_lines, str):
|
||||
self.write_line(line_or_lines)
|
||||
else:
|
||||
for line in line_or_lines:
|
||||
self.write_line(line)
|
||||
|
||||
def pytest_report_header(self, config: Config) -> List[str]:
|
||||
line = "rootdir: %s" % config.rootdir
|
||||
|
|
|
@ -283,3 +283,22 @@ class TestRaises:
|
|||
with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload]
|
||||
pass
|
||||
assert "Unexpected keyword arguments" in str(excinfo.value)
|
||||
|
||||
def test_expected_exception_is_not_a_baseexception(self) -> None:
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
with pytest.raises("hello"): # type: ignore[call-overload]
|
||||
pass # pragma: no cover
|
||||
assert "must be a BaseException type, not str" in str(excinfo.value)
|
||||
|
||||
class NotAnException:
|
||||
pass
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
with pytest.raises(NotAnException): # type: ignore[type-var]
|
||||
pass # pragma: no cover
|
||||
assert "must be a BaseException type, not NotAnException" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
with pytest.raises(("hello", NotAnException)): # type: ignore[arg-type]
|
||||
pass # pragma: no cover
|
||||
assert "must be a BaseException type, not str" in str(excinfo.value)
|
||||
|
|
Loading…
Reference in New Issue