Skip to content

Fix monkeypatch undo of inherited attributes - #14944

Closed
arpansahu wants to merge 1 commit into
pytest-dev:mainfrom
arpansahu:fix/monkeypatch-inherited-attr-undo
Closed

Fix monkeypatch undo of inherited attributes#14944
arpansahu wants to merge 1 commit into
pytest-dev:mainfrom
arpansahu:fix/monkeypatch-inherited-attr-undo

Conversation

@arpansahu

Copy link
Copy Markdown

Problem

When MonkeyPatch.setattr() patches an inherited attribute on an instance, undo restores the inherited value into the instance __dict__. This leaves the object in a different state after cleanup; for descriptors, it also shadows future descriptor lookup. Closes #10644.

Reproducer

from _pytest.monkeypatch import MonkeyPatch

class Parent:
    x = 1

target = Parent()
mp = MonkeyPatch()
mp.setattr(target, "x", 2)
mp.undo()
print(vars(target))
# current: {'x': 1}
# expected: {}

Fix

For non-class targets, record NOTSET when the patched name is not present in the instance dictionary. undo() then deletes the temporary instance attribute and exposes the inherited attribute again, matching the original object state.

Testing

  • Added testing/test_monkeypatch.py::test_setattr_inherited_attribute_undo_restores_instance_dict.
  • Before fix: the new test failed with AssertionError: assert 'x' not in {'x': 1}.
  • After fix: 1 passed.
  • python -m pytest testing/test_monkeypatch.py -q36 passed, 1 skipped.
  • python -m ruff check src/_pytest/monkeypatch.py testing/test_monkeypatch.pyAll checks passed!.
  • python -m ruff format --check src/_pytest/monkeypatch.py testing/test_monkeypatch.py2 files already formatted.

Full suite note: python -m pytest testing/ -q --tb=short --maxfail=1 reaches a pre-existing Windows failure in testing/acceptance_test.py::TestGeneralUsage::test_file_not_found_unconfigure_issue143 (ExitCode.INTERNAL_ERROR vs ExitCode.USAGE_ERROR) after 1769 passed.

Checklist:

  • Include new tests or update existing tests when applicable.
  • Allow maintainers to push and squash when merging my commits.
  • Add text like closes #XYZW to the PR description and/or commits.
  • If AI agents were used, they are credited in Co-authored-by commit trailers.
  • Create a new changelog file in the changelog directory.
  • Add yourself to AUTHORS in alphabetical order.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: arpan sahu <28574248+arpansahu@users.noreply.github.com>
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Aug 27, 2026
@arpansahu

Copy link
Copy Markdown
Author

Disclosure: this contribution was prepared with AI assistance (GitHub Copilot CLI), and
I am flagging that explicitly rather than leaving you to guess.

The defect, the fix and the regression test were verified locally: the new test fails on
unmodified upstream and passes with the change applied, and the surrounding suite is green.

If your project would prefer not to take AI-assisted contributions, or you would rather this
were reworked and resubmitted by hand, please just close it -- no objection at all, and
apologies for the noise.

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

Redo of preexisting pr in a much worse way

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.setattr leaves a new item in vars(target) after cleanup when overriding an inherited attribute of a non-class object

2 participants