Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

monkeypatch.setattr fails to undo on objects with a custom __setattr__ (regression from #14969)

オープン 初心者向け
#15,099 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@Maurenz2530 がすでに取り組んでいます。

2026年9月26日 から。

  • #15104 @Maurenz2530 による — オープン
  • #15106 @chen-maker999 による — マージされずにクローズ
  • #15118 @Tejas5405 による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
testing-qa

調査の方向性

MonkeyPatch.setattr の新しい分岐から始め、issue に記載された以前の動作と比較します。test_proxy.py にカスタム setattr/getattr オブジェクトを使ったリグレッションケースを追加し、そのテストを実行して、undo によって元の値が復元され、パッチ適用された値が後続のテストに漏れないことを確認します。

索引モデルが issue の本文から書いたものです。

説明

Since #14969 (0c601d510, not released yet), monkeypatch.setattr doesn't restore attributes on objects that store them somewhere other than __dict__ through a custom __setattr__/__getattr__. Undo raises AttributeError, and the patched value leaks into later tests.

class Config:
    """Stores attributes in a private dict instead of __dict__."""
    def __init__(self):
        object.__setattr__(self, "_data", {"debug": False})
    def __getattr__(self, name):
        try:
            return self._data[name]
        except KeyError:
            raise AttributeError(name) from None
    def __setattr__(self, name, value):
        self._data[name] = value

cfg = Config()

def test_patch(monkeypatch):
    monkeypatch.setattr(cfg, "debug", True)
    assert cfg.debug is True

def test_restored():
    assert cfg.debug is False

On main:

ERROR test_proxy.py::test_patch - AttributeError: 'Config' object has no attribute 'debug'
FAILED test_proxy.py::test_restored - assert True is False
1 failed, 1 passed, 1 error

Just before 0c601d510, the same file passes (2 passed).

The new branch in MonkeyPatch.setattr takes the old value from target.__dict__.get(name, NOTSET) whenever target has a __dict__. It assumes that a plain setattr() writes into that dict. With a custom __setattr__ it doesn't, so the old value is recorded as NOTSET. undo() then calls delattr(cfg, "debug") instead of setting it back to False. That delattr fails, and the value stays patched.

@Shriprasad-P pointed out this exact case in a review on #14969, but it wasn't addressed before the merge. I'm opening this issue so it gets fixed before the next release.

One possible direction: only use the __dict__ lookup when name is actually present in the instance __dict__, or when the type uses object.__setattr__. Otherwise fall back to the value from getattr(), as before.

pytest 9.2.0.dev345+g872117358, Python 3.13.5, Windows 11.

主要言語
Python
スター
14.6k
フォーク
3.4k
平均マージ
1日 23時間
マージ済み PR(30日)
31

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

pytest-dev/pytest のほかの issue

pytest-dev/pytest の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。