diff --git a/pyproject.toml b/pyproject.toml index a4139a5c0..8432d5d2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" write_to = "src/_pytest/_version.py" [tool.pytest.ini_options] -minversion = "2.0" +#minversion = "2.0" addopts = "-rfEX -p pytester --strict-markers" python_files = ["test_*.py", "*_test.py", "testing/python/*.py"] python_classes = ["Test", "Acceptance"] diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index a60f34671..9d8816556 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -206,23 +206,26 @@ class WarningsRecorder(warnings.catch_warnings): # type:ignore[type-arg] return len(self._list) def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": - """Pop the first recorded warning (or subclass of warning), raise exception if not exists.""" - matches = [] + """Pop the first recorded warning which is an instance of ``cls``. + + But not an instance of a child class of any other match. + Raises ``AssertionError`` if there is no match. + + """ + + best_idx = None for i, w in enumerate(self._list): if w.category == cls: - return self._list.pop(i) - if issubclass(w.category, cls): - matches.append((i, w)) - if not matches: - __tracebackhide__ = True - raise AssertionError(f"{cls!r} not found in warning list") - (idx, best), *rest = matches - for i, w in rest: - if issubclass(w.category, best.category) and not issubclass( - best.category, w.category + return self._list.pop(i) # exact match, stop looking + if issubclass(w.category, cls) and ( + best_idx is None + or not issubclass(w.category, self._list[best_idx].category) # type: ignore[unreachable] ): - idx, best = i, w - return self._list.pop(idx) + best_idx = i + if best_idx is not None: + return self._list.pop(best_idx) + __tracebackhide__ = True + raise AssertionError(f"{cls!r} not found in warning list") def clear(self) -> None: """Clear the list of recorded warnings.""" diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 6c2dc4660..3a35c255e 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -72,10 +72,12 @@ class TestSubclassWarningPop: def test_pop_most_recent(self): with pytest.warns(self.ParentWarning) as record: - self.raise_warnings_from_list([self.ChildWarning, self.ChildOfChildWarning]) + self.raise_warnings_from_list( + [self.ChildOfChildWarning, self.ChildWarning, self.ChildOfChildWarning] + ) _warn = record.pop(self.ParentWarning) - assert _warn.category is self.ChildOfChildWarning + assert _warn.category is self.ChildWarning class TestWarningsRecorderChecker: