You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WarningsRecorder.pop() returns the last match instead of the first when warning categories are unrelated #15097
WarningsRecorder.pop() (and pytest.warns(...).pop() / recwarn.pop()) returns the last matching warning instead of the first one when the recorded warnings have categories that are unrelated to each other.
The docstring says pop returns "the first recorded warning which is an instance of cls, but not an instance of a child class of any other match". None of the three categories is a subclass of another, so the first one should come back. That was also the behaviour before 8.0.
The cause is the "best inexact match" loop added in #11160 (the fix for #10701):
ifissubclass(w.category, cls) and (
best_idxisNoneornotissubclass(w.category, self._list[best_idx].category)
):
best_idx=i
not issubclass(new, best) is true both when new is more general than bestand when the two are unrelated siblings. So every sibling replaces the current best, and the loop ends up on the last one.
The existing tests in TestSubclassWarningPop only use a single parent/child chain, so they don't catch this. test_recording pops a UserWarning and a DeprecationWarning, but both have the message "hello", so it passes whichever one comes back.
Reproduced on main (pytest 9.2.0.dev345+g872117358), Python 3.13.5, Windows 11. The loop was introduced by #11160, so the bug is present since 8.0.0; in 7.4.x pop() returned the first match. I have a fix with regression tests ready and will open a PR.
Reproduced on main (9.2.0.dev450, Python 3.13): popping from a recorder holding a UserWarning, a RuntimeWarning and a DeprecationWarning returns the last one (assert 'third' == 'first').
Your analysis of the cause matches what I found: not issubclass(w.category, best_category) is also true for unrelated siblings, so every new match displaces the previous best and the loop ends on the last one.
Restricting the replacement to the case where the current best is a strict subclass of the new category -- that is, the new match is strictly more general -- restores the documented "first match which is not a child class of any other match" behaviour, and keeps the parent/child preference that #11160 added for #10701 (the existing test_pop_finds_best_inexact_match still passes).
I'll send a pull request with two regression tests (unrelated categories, and a repeated category so the first one is kept) plus a changelog entry.
Disclosure per the project's AI/LLM policy: this is an AI-assisted contribution; the pull request states what was machine-produced and what I verified manually.
Activity
Tejas5405 commentedon Oct 1, 2026
Reproduced on main (9.2.0.dev450, Python 3.13): popping from a recorder holding a
UserWarning, aRuntimeWarningand aDeprecationWarningreturns the last one (assert 'third' == 'first').Your analysis of the cause matches what I found:
not issubclass(w.category, best_category)is also true for unrelated siblings, so every new match displaces the previous best and the loop ends on the last one.Restricting the replacement to the case where the current best is a strict subclass of the new category -- that is, the new match is strictly more general -- restores the documented "first match which is not a child class of any other match" behaviour, and keeps the parent/child preference that #11160 added for #10701 (the existing
test_pop_finds_best_inexact_matchstill passes).I'll send a pull request with two regression tests (unrelated categories, and a repeated category so the first one is kept) plus a changelog entry.
Disclosure per the project's AI/LLM policy: this is an AI-assisted contribution; the pull request states what was machine-produced and what I verified manually.
fix(recwarn): `pop()` returns the first match for unrelated categories
test(recwarn): lock down which match `pop()` returns