Skip to content

Fix monkeypatch.setattr() teardown crash on failed setattr#14209

Merged
Pierre-Sassoulas merged 2 commits into
pytest-dev:mainfrom
worksbyfriday:fix-monkeypatch-setattr-undo
May 23, 2026
Merged

Fix monkeypatch.setattr() teardown crash on failed setattr#14209
Pierre-Sassoulas merged 2 commits into
pytest-dev:mainfrom
worksbyfriday:fix-monkeypatch-setattr-undo

Conversation

@worksbyfriday

Copy link
Copy Markdown
Contributor

Fixes #14161.

When monkeypatch.setattr(target, name, value, raising=False) is called on a target that doesn't support attribute setting (e.g. None or other immutable objects), the underlying setattr() raises AttributeError. But the undo stack entry was appended before the setattr() call, leaving a stale (target, name, NOTSET) entry. During teardown, undo() then tries delattr(target, name), causing a second AttributeError crash.

Fix: Move the _setattr.append() call after the setattr() call, so only successful attribute modifications get undo entries.

# Before: crashes at teardown
something_or_none = None
monkeypatch.setattr(something_or_none, 'do_something', fake, raising=False)
# → setattr fails, but undo stack has stale entry
# → teardown: delattr(None, 'do_something') → AttributeError

# After: teardown is clean
# → setattr fails, undo stack is empty
# → teardown: nothing to undo

…v#14161)

When setattr() fails (e.g. because the target is immutable like None),
the undo stack already had the entry appended before the setattr call.
This left a stale (target, name, NOTSET) entry that would crash during
teardown with AttributeError trying to delattr on the target.

Fix by moving the _setattr.append() after the setattr() call, so
failed setattr operations don't pollute the undo stack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Feb 18, 2026

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, thanks

if you like you can use

with monkeypatch.context() as ctx:
       with pytest.raises(...):
          ctx.setattr(...)

to pin down the monkey-patch used to something very constrained

@Pierre-Sassoulas Pierre-Sassoulas merged commit 47ed628 into pytest-dev:main May 23, 2026
33 checks passed
@Pierre-Sassoulas Pierre-Sassoulas added this to the 9.1 milestone May 23, 2026
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.

Monkeypatch raising having no effect at tear down

3 participants