patch does not correctly restore state on objects without __dict__
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 77.2k
- Forks
- 35.9k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug report
Bug description:
from unittest.mock import patch
class Proxy(object):
config = {}
def __getattr__(self, name):
return self.config[name]
def __setattr__(self, name, value):
if name == 'config':
object.__setattr__(self, name, value)
return
self.config[name] = value
def __delattr__(self, name):
self.config[name] = 'DEFAULT'
p = Proxy()
p.a = True
print(p.a)
with patch('__main__.p.a', False):
print(p.a)
print(p.a)
Expected
True
False
True
Actual
True
False
DEFAULT
Note that this is a relatively niche issue, but for example in a config system (i.e. https://github.com/pytorch/pytorch/pull/140779), if you don't want to have a delete work, (i.e. have it set it back to a default value), the code in https://github.com/python/cpython/blob/94a7a4e22fb8f567090514785c69e65298acca42/Lib/unittest/mock.py#L1637 will call delattr, and then not call setattr, because it still has the attr.
Possible fixes:
If delattr throws (maybe NotImplementederror), call setattr instead (this is nice and explicit + removes the hacky workaround I have to do).
If the value after it's been deleted doesn't equal the original value, reassign it? (this might require objects to be comparable, not sure if that is already an issue here).
Either way I wanted to see if there was any interest in fixing this, and if anyone saw a solution that seemed reasonable enough.
CPython versions tested on:
3.12
Operating systems tested on:
Linux
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit der Reproduktion im Issue und untersuche die Wiederherstellungslogik in Lib/unittest/mock.py um Zeile 1637. Vergleiche, wie patch Attribute von Objekten ohne dict behandelt, wenn das Löschen den beobachteten Wert verändert. Erledigt ist die Aufgabe, wenn das Beispiel p.a auf True wiederherstellt und dabei das bestehende Verhalten für gewöhnliche Objekte beibehält; füge außerdem eine Regressionstestabdeckung in den relevanten unittest.mock-Tests hinzu.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- testing-qa
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100