jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1319943?usp=email )
Change subject: tests: Add assertHasItems helper for non-empty iterables ......................................................................
tests: Add assertHasItems helper for non-empty iterables
Bug: T433792 Change-Id: Ib33242b0608433302efd6482d7ed33e9a24e83a7 --- M tests/aspects.py 1 file changed, 49 insertions(+), 5 deletions(-)
Approvals: jenkins-bot: Verified Xqt: Looks good to me, approved
diff --git a/tests/aspects.py b/tests/aspects.py index 589bd97..9486323 100644 --- a/tests/aspects.py +++ b/tests/aspects.py @@ -22,6 +22,8 @@ from contextlib import contextmanager, suppress from functools import wraps from http import HTTPStatus +from itertools import chain +from typing import TypeVar from unittest.util import safe_repr
import pywikibot @@ -58,6 +60,7 @@ )
+T = TypeVar('T') OSWIN32 = (sys.platform == 'win32') SIZED_ERROR = 'seq argument is not a Sized class containing __len__'
@@ -249,22 +252,32 @@ """Base class for all tests."""
def assertIsEmpty(self, seq, msg=None) -> None: - """Check that the sequence is empty.""" + """Check that the sequence is empty. + + .. version-added:: 3.0.20200703 + """ self.assertIsInstance(seq, Sized, SIZED_ERROR) if seq: msg = self._formatMessage(msg, f'{safe_repr(seq)} is not empty') self.fail(msg)
def assertIsNotEmpty(self, seq, msg=None) -> None: - """Check that the sequence is not empty.""" + """Check that the sequence is not empty. + + .. version-added:: 3.0.20200703 + """ self.assertIsInstance(seq, Sized, SIZED_ERROR) if not seq: msg = self._formatMessage(msg, f'{safe_repr(seq)} is empty') self.fail(msg)
def assertLength(self, seq, other, msg=None) -> None: - """Verify that a sequence seq has the length of other.""" - # the other parameter may be given as a sequence too + """Verify that a sequence seq has the length of other. + + The *other* parameter may be given as a sequence too + + .. version-added:: 3.0.20200703 + """ self.assertIsInstance(seq, Sized, SIZED_ERROR) first_len = len(seq) try: @@ -277,6 +290,37 @@ msg, f'len({safe_repr(seq)}): {first_len} != {second_len}') self.fail(msg)
+ def assertHasItems( + self, + iterable: Iterable[T], + msg: str | None = None, + ) -> Iterator[T]: + """Assert that an iterable yields at least one item. + + Return an iterator yielding all items from *iterable*, including + the first one. + + .. note:: + If *iterable* is an iterator, use the returned iterator + instead of the original one. + + .. version-added:: 11.7 + + :param iterable: Iterable to check. + :param msg: The message to be shown on failure. + :return: An iterator yielding all items from *iterable*. + """ + missing = sentinel('MISSING') + iterator = iter(iterable) + first = next(iterator, missing) + + if first is missing: + msg = self._formatMessage( + msg, f'{safe_repr(iterable)} yields no items') + self.fail(msg) + + return chain((first,), iterator) + def assertPageInNamespaces(self, page, namespaces: int | set[int]) -> None: """Assert that Pages is in namespaces.
@@ -301,7 +345,7 @@ the *count* parameter was dropped; all pages from *gen* are tested.
- :param gen: Page generator + :param gen: Page iterable :param site: Site of expected pages :meta public: """
pywikibot-commits@lists.wikimedia.org