BugFix #14329 - #14332
Conversation
4374480 to
5d467d3
Compare
bluetech
left a comment
There was a problem hiding this comment.
Thanks, the changes LGTM. I pushed a few tweaks.
I'll let others a few days to review, then merge.
RonnyPfannschmidt
left a comment
There was a problem hiding this comment.
Under strict pedantic this is a breaking change
Im a bit torn for the classification
|
Under strict pedantic every bug fix is a breaking change 😀 I think this case is sensible for a minor release. I don't actually expect the MRO thing to come up that much... |
|
Maybe the usefixtures change could be a bit more disruptive, but it will be annoying to separate the two... |
|
The order of items changes slightly That likes to break things |
What items are you referring to here? The mark list items, or the Items (tests) order changing due to usefixture changes?
Would you prefer to defer this PR to pytest 10? |
…O marker Fix get_closest_marker and iter_markers to return markers in correct closest-first order when class inheritance (MRO) is involved (pytest-dev#14329). Previously, own_markers on Class nodes stored MRO-inherited markers in base-first (farthest) order, and iter_markers yielded them in that same order. This caused get_closest_marker to return a base class marker instead of the overriding child class marker. The fix introduces _iter_own_markers_closest_first() on Node, overridden by Class to walk the MRO in natural closest-first order while preserving decorator stacking order within each class. This avoids changing own_markers (keeping its base-first construction order) and avoids breaking parametrize naming order. Also reverses usefixtures marker iteration to maintain farthest-first setup ordering (module -> base class -> child class -> function). Alternative structural approach to PR pytest-dev#14332 that preserves own_markers order for backward compatibility. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4.6 <claude@anthropic.com>
…O marker Fix get_closest_marker and iter_markers to return markers in correct closest-first order when class inheritance (MRO) is involved (pytest-dev#14329). Previously, own_markers on Class nodes stored MRO-inherited markers in base-first (farthest) order, and iter_markers yielded them in that same order. This caused get_closest_marker to return a base class marker instead of the overriding child class marker. The fix introduces _iter_own_markers_closest_first() on Node, overridden by Class to walk the MRO in natural closest-first order while preserving decorator stacking order within each class. This avoids changing own_markers (keeping its base-first construction order) and avoids breaking parametrize naming order. Also reverses usefixtures marker iteration to maintain farthest-first setup ordering (module -> base class -> child class -> function). Alternative structural approach to PR pytest-dev#14332 that preserves own_markers order for backward compatibility. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4.6 <claude@anthropic.com>
…O marker Fix get_closest_marker and iter_markers to return markers in correct closest-first order when class inheritance (MRO) is involved (pytest-dev#14329). Previously, own_markers on Class nodes stored MRO-inherited markers in base-first (farthest) order, and iter_markers yielded them in that same order. This caused get_closest_marker to return a base class marker instead of the overriding child class marker. The fix introduces _iter_own_markers_closest_first() on Node, overridden by Class to walk the MRO in natural closest-first order while preserving decorator stacking order within each class. This avoids changing own_markers (keeping its base-first construction order) and avoids breaking parametrize naming order. Also reverses usefixtures marker iteration to maintain farthest-first setup ordering (module -> base class -> child class -> function). Alternative structural approach to PR pytest-dev#14332 that preserves own_markers order for backward compatibility. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4.6 <claude@anthropic.com>
The regression test for pytest-dev#14329 is Wintreist's, taken verbatim from pytest-dev#14332; carry the attribution and add them to AUTHORS. Also spell out the parametrize consequence in the changelog: class level `parametrize` markers are consumed through `iter_markers`, so inherited ones now compose IDs closest-first (`[1-x]` -> `[x-1]`). That invalidates pinned ID selections and the `--last-failed` cache, which is worth more warning than the marker reorder itself. Co-authored-by: Wintreist <49996562+Wintreist@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`_lookup_derived` scanned `own_markers` front-to-back and returned the first name match, but the eager `keywords.update((mark.name, mark) ...)` it replaces let *later* markers win. A Class stores MRO-inherited markers base class first, so `keywords["foo"]` silently changed from the subclass' marker to the base class' one. Scan in reverse instead. Note this direction is tied to `own_markers` order: it has to flip if pytest-dev#14332 lands rather than pytest-dev#14630. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks for the patience here, and sorry it took this long to get to a decision. I'm going to land #14630 instead and close this one — but your test goes in with it verbatim, with a The concrete reason: reversing self.keywords.update((mark.name, mark) for mark in self.own_markers)which is last-wins. With base-first @pytest.mark.foo("base")
class TestBase: pass
@pytest.mark.foo("child")
class TestChild(TestBase):
def test_it(self, request):
request.node.parent.keywords["foo"].args[0] # "child" on main, "base" with this PRNothing in the suite catches it — #14630 leaves For the record, one of my claims about this PR was wrong, and I've corrected it on mine: I said reversing breaks parametrize ID ordering in a way an iteration-layer fix avoids. It doesn't. @bluetech you approved this one — say the word if you'd rather go this way instead, reopening is cheap. |
Closes #14329
Fixed the issue of getting the really closest label to the test. I abolished the priority of base classes over labels, but supported getting the
usefixturesmark in reverse order (i.e. from the base class to the heir), since this is a unique case when you really need to call fixtures sequentially from the base class.I did not add myself to the Authors, as I do not plan to be a pytest developer yet, I fixed the problem, as it interferes with my main project. Thanks