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 =
|
install_requires =
|
||||||
attrs>=17.4.0
|
attrs>=17.4.0
|
||||||
iniconfig
|
iniconfig
|
||||||
more-itertools>=4.0.0
|
|
||||||
packaging
|
packaging
|
||||||
pluggy>=0.12,<1.0
|
pluggy>=0.12,<1.0
|
||||||
py>=1.8.2
|
py>=1.8.2
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import itertools
|
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
@ -1489,10 +1488,10 @@ class FixtureManager:
|
||||||
else:
|
else:
|
||||||
argnames = ()
|
argnames = ()
|
||||||
|
|
||||||
usefixtures = itertools.chain.from_iterable(
|
usefixtures = tuple(
|
||||||
mark.args for mark in node.iter_markers(name="usefixtures")
|
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
|
fm = node.session._fixturemanager
|
||||||
initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure(
|
initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure(
|
||||||
initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
|
initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import inspect
|
|
||||||
import math
|
import math
|
||||||
import pprint
|
import pprint
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from collections.abc import Sized
|
from collections.abc import Sized
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from itertools import filterfalse
|
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -18,8 +16,6 @@ from typing import Tuple
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from more_itertools.more import always_iterable
|
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
from _pytest.compat import overload
|
from _pytest.compat import overload
|
||||||
from _pytest.compat import STRING_TYPES
|
from _pytest.compat import STRING_TYPES
|
||||||
|
@ -30,9 +26,6 @@ if TYPE_CHECKING:
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
|
|
||||||
BASE_TYPE = (type, STRING_TYPES)
|
|
||||||
|
|
||||||
|
|
||||||
def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
|
def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
|
||||||
at_str = " at {}".format(at) if at else ""
|
at_str = " at {}".format(at) if at else ""
|
||||||
return TypeError(
|
return TypeError(
|
||||||
|
@ -680,11 +673,16 @@ def raises( # noqa: F811
|
||||||
documentation for :ref:`the try statement <python:try>`.
|
documentation for :ref:`the try statement <python:try>`.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
for exc in filterfalse(
|
|
||||||
inspect.isclass, always_iterable(expected_exception, BASE_TYPE)
|
if isinstance(expected_exception, type):
|
||||||
):
|
excepted_exceptions = (expected_exception,) # type: Tuple[Type[_E], ...]
|
||||||
msg = "exceptions must be derived from BaseException, not %s"
|
else:
|
||||||
raise TypeError(msg % type(exc))
|
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)
|
message = "DID NOT RAISE {}".format(expected_exception)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ from typing import Union
|
||||||
import attr
|
import attr
|
||||||
import pluggy
|
import pluggy
|
||||||
import py
|
import py
|
||||||
from more_itertools import collapse
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
|
@ -715,10 +714,13 @@ class TerminalReporter:
|
||||||
self._write_report_lines_from_hooks(lines)
|
self._write_report_lines_from_hooks(lines)
|
||||||
|
|
||||||
def _write_report_lines_from_hooks(
|
def _write_report_lines_from_hooks(
|
||||||
self, lines: List[Union[str, List[str]]]
|
self, lines: Sequence[Union[str, Sequence[str]]]
|
||||||
) -> None:
|
) -> None:
|
||||||
lines.reverse()
|
for line_or_lines in reversed(lines):
|
||||||
for line in collapse(lines):
|
if isinstance(line_or_lines, str):
|
||||||
|
self.write_line(line_or_lines)
|
||||||
|
else:
|
||||||
|
for line in line_or_lines:
|
||||||
self.write_line(line)
|
self.write_line(line)
|
||||||
|
|
||||||
def pytest_report_header(self, config: Config) -> List[str]:
|
def pytest_report_header(self, config: Config) -> List[str]:
|
||||||
|
|
|
@ -283,3 +283,22 @@ class TestRaises:
|
||||||
with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload]
|
with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload]
|
||||||
pass
|
pass
|
||||||
assert "Unexpected keyword arguments" in str(excinfo.value)
|
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