-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Open
Description
Hi.
The issue
So if I pass an object that lacks a property or dict that lacks an item to delattr and delitem respectively, by default those methods fail with an Exception.
So by setting raising=False, the exception is skipped. But the monkeypatch object does not record that the object originally lacked the property.
If after the unit test adds the attribute or item, monkeypatch will not restore the object original state, by deleted the attribute or item added by the test.
Here's code examples that show the issue in detail.
# 1. Not an issue
obj = {1:2}
with pytest.Monkeypatch.context() as mp:
mp.delitem(obj, 1)
obj[1] = 3
assert obj[1] == 2 # PASS ! the delitem operation was reversed and the original value was restored
# 2. This is an issue
obj = {}
with pytest.Monkeypatch.context() as mp:
mp.delitem(obj, 1, raising=False)
obj[1] = 3
# FAIL ! the delitem operation was not reversed since the original object did not have the property
# and the mp object did not record a NOTSET value
assert 1 not in obj
This applies equally to attributes, e.g. obj = types.SimpleNamespace() and change obj[1] to obj.prop.
The solution
diff --git a/monkeypatch.py b/monkeypatch.py
index 1285e57..92bf43e 100644
--- a/monkeypatch.py
+++ b/monkeypatch.py
@@ -280,6 +280,7 @@ def delattr(self, target: object | str, name: str | Notset = notset, raising: bool = True) -> None:
if not hasattr(target, name):
if raising:
raise AttributeError(name)
+ self._setattr.append((target, name, notset))
else:
oldval = getattr(target, name, notset)
# Avoid class descriptors like staticmethod/classmethod.
@@ -303,6 +304,7 @@ def delitem(self, dic: Mapping[K, V], name: K, raising: bool = True) -> None:
if name not in dic:
if raising:
raise KeyError(name)
+ self._setitem.append((dic, name, notset))
else:
self._setitem.append((dic, name, dic.get(name, notset)))
# Not all Mapping types support indexing, but MutableMapping doesn't support TypedDictEnvironment
Any OS, issue present in the current code
https://github.com/pytest-dev/pytest/blob/main/src/_pytest/monkeypatch.py#L250
Metadata
Metadata
Assignees
Labels
No labels