From 460af385bf44d5b637eec6f0b4b35a850a0fc07c Mon Sep 17 00:00:00 2001 From: Aditya Kumar Date: Thu, 24 Sep 2026 23:20:56 +0530 Subject: [PATCH 1/2] recwarn: return first unrelated match from WarningsRecorder.pop() The "best inexact match" loop replaced the current best whenever the new category was not a subclass of it, which also holds for unrelated sibling categories, so pop() returned the last recorded warning instead of the first. Return the first match whose category is not a strict subclass of another match's category, as the docstring describes. Fixes #15097. --- AUTHORS | 1 + changelog/15097.bugfix.rst | 1 + src/_pytest/recwarn.py | 20 ++++++++++---------- testing/test_recwarn.py | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 changelog/15097.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e2fad5e8364..413d146d351 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,6 +11,7 @@ ace2016 Adam Johnson Adam Stewart Adam Uhlir +Aditya Kumar Aditya Tripuraneni Ahn Ki-Wook Akhilesh Ramakrishnan diff --git a/changelog/15097.bugfix.rst b/changelog/15097.bugfix.rst new file mode 100644 index 00000000000..5376093d809 --- /dev/null +++ b/changelog/15097.bugfix.rst @@ -0,0 +1 @@ +:meth:`WarningsRecorder.pop() ` now returns the first matching warning again when the recorded warnings have unrelated categories, instead of the last one. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 3e36fc7d286..eb5a798a580 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -213,17 +213,17 @@ def pop(self, cls: type[Warning] = Warning) -> warnings.WarningMessage: but not an instance of a child class of any other match. Raises ``AssertionError`` if there is no match. """ - best_idx: int | None = None - for i, w in enumerate(self._list): - if w.category == cls: - 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) + matches = [ + (i, w.category) + for i, w in enumerate(self._list) + if issubclass(w.category, cls) + ] + for i, category in matches: + if not any( + other is not category and issubclass(category, other) + for _, other in matches ): - best_idx = i - if best_idx is not None: - return self._list.pop(best_idx) + return self._list.pop(i) __tracebackhide__ = True raise AssertionError(f"{cls!r} not found in warning list") diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index d6de42a4c5c..99eef7795c2 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -82,6 +82,25 @@ def test_pop_finds_best_inexact_match(self): _warn = record.pop(self.ParentWarning) assert _warn.category is self.ChildWarning + def test_pop_finds_first_of_unrelated_matches(self): + with pytest.warns(Warning) as record: + self.raise_warnings_from_list( + [self.ChildWarning, UserWarning, DeprecationWarning] + ) + + assert record.pop().category is self.ChildWarning + assert record.pop().category is UserWarning + assert record.pop().category is DeprecationWarning + + def test_pop_skips_child_of_later_match(self): + with pytest.warns(Warning) as record: + self.raise_warnings_from_list( + [self.ChildWarning, UserWarning, self.ParentWarning] + ) + + _warn = record.pop() + assert _warn.category is UserWarning + class TestWarningsRecorderChecker: def test_recording(self) -> None: From f33818b206a29a490baacac16dc135e2ecb243b2 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Date: Fri, 25 Sep 2026 15:56:29 +0530 Subject: [PATCH 2/2] Re-trigger CI (changelog check did not report)