Skip to content

feat(rewrite): introspect container[key] in failure messages - #14815

Draft
RonnyPfannschmidt wants to merge 4 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:ronny/rewrite-visit-subscript
Draft

feat(rewrite): introspect container[key] in failure messages#14815
RonnyPfannschmidt wants to merge 4 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:ronny/rewrite-visit-subscript

Conversation

@RonnyPfannschmidt

@RonnyPfannschmidt RonnyPfannschmidt commented Jul 31, 2026

Copy link
Copy Markdown
Member

Stacked on #14814#14447#14921#14813. Its diff includes theirs.

A subscript was opaque: the message showed the value it produced with no indication of which container or key it came from. Decompose it the way attribute access already is.

assert 1 == 99
 +  where 1 = {'a': 1, 'b': 2}['a']

Slices keep the generic treatment; decomposing start/stop/step is rarely what a failure message needs.

The container goes through visit_operand(), because taking the expression away from generic_visit takes away the hoisting that kept it ordered. Without that, assert box[identity(box := other)] == 1 would start reading the post-walrus container — a bug this PR would have introduced. The order-subscript-container guard in #14813 fails if the freeze is dropped; I checked by dropping it.

This is what the guards in that matrix are for: they are passing tests on main precisely so that a new visitor cannot quietly regress them.

Lands the introspect-subscript cases of the coverage matrix in #14813, as passing tests (+3).

Supersedes part of #14448.

RonnyPfannschmidt and others added 4 commits September 1, 2026 13:51
visit_operand() only froze a bare name, so two other unhoisted operands
kept being evaluated after everything that follows them:

    assert collect((x := 1), identity(x := 2)) == (1, 2)
    assert collect(*items, identity(items := [9])) == (1, [9])

A walrus operator left in place assigns once the enclosing expression is
assembled, which is after the later arguments have run -- so the earlier
argument saw the later assignment.  A starred argument hid its value
inside an ast.Starred, where the existing Name check could not see it.

Closes the order-starred-argument group and the remaining
order-call-argument entry in the coverage matrix.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eeds

visit_operand freezes a walrus operand whenever anything follows it, and
a comparison always has at least one comparator -- so by the time
visit_Compare looks at its left operand, a NamedExpr has already been
copied into a temporary.  The special case that did it here can never
run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rewriter only ever visits expressions inside an assert condition, so
an attribute always arrives in Load context and the fallback never runs.
Removing it keeps the next visitor from copying a guard that cannot fire.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A subscript was opaque: the message showed the value it produced with no
indication of which container or key it came from.  Decompose it the way
attribute access already is.

The container goes through visit_operand() because taking the expression
away from generic_visit() takes away the hoisting that kept it ordered --
without that, `assert box[identity(box := other)] == 1` would start
reading the post-walrus container.  The order-axis guard in the coverage
matrix fails if this is dropped.

Slices keep the generic treatment; decomposing start/stop/step is rarely
what a failure message needs.

Closes the introspect-subscript group in the coverage matrix.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the ronny/rewrite-visit-subscript branch from b3d36ca to aec8d2d Compare September 1, 2026 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant