Bugfix: monkeypatch.delattr handles class descriptors
Correct monkeypatch.delattr to match the correct behavior of monkeypatch.setattr when changing class descriptors
This commit is contained in:
parent
6af674a3ac
commit
f8d31d2400
1
AUTHORS
1
AUTHORS
|
@ -48,6 +48,7 @@ Christian Boelsen
|
||||||
Christian Theunert
|
Christian Theunert
|
||||||
Christian Tismer
|
Christian Tismer
|
||||||
Christopher Gilling
|
Christopher Gilling
|
||||||
|
Christopher Dignam
|
||||||
CrazyMerlyn
|
CrazyMerlyn
|
||||||
Cyrus Maden
|
Cyrus Maden
|
||||||
Dhiren Serai
|
Dhiren Serai
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
monkeypatch.delattr handles class descriptors like staticmethod/classmethod
|
|
@ -181,6 +181,8 @@ class MonkeyPatch(object):
|
||||||
attribute is missing.
|
attribute is missing.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
import inspect
|
||||||
|
|
||||||
if name is notset:
|
if name is notset:
|
||||||
if not isinstance(target, six.string_types):
|
if not isinstance(target, six.string_types):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
|
@ -194,7 +196,11 @@ class MonkeyPatch(object):
|
||||||
if raising:
|
if raising:
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
else:
|
else:
|
||||||
self._setattr.append((target, name, getattr(target, name, notset)))
|
oldval = getattr(target, name, notset)
|
||||||
|
# avoid class descriptors like staticmethod/classmethod
|
||||||
|
if inspect.isclass(target):
|
||||||
|
oldval = target.__dict__.get(name, notset)
|
||||||
|
self._setattr.append((target, name, oldval))
|
||||||
delattr(target, name)
|
delattr(target, name)
|
||||||
|
|
||||||
def setitem(self, dic, name, value):
|
def setitem(self, dic, name, value):
|
||||||
|
|
|
@ -391,6 +391,33 @@ def test_issue156_undo_staticmethod(Sample):
|
||||||
assert Sample.hello()
|
assert Sample.hello()
|
||||||
|
|
||||||
|
|
||||||
|
def test_undo_class_descriptors_delattr():
|
||||||
|
class SampleParent(object):
|
||||||
|
@classmethod
|
||||||
|
def hello(_cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def world():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SampleChild(SampleParent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
monkeypatch = MonkeyPatch()
|
||||||
|
|
||||||
|
original_hello = SampleChild.hello
|
||||||
|
original_world = SampleChild.world
|
||||||
|
monkeypatch.delattr(SampleParent, "hello")
|
||||||
|
monkeypatch.delattr(SampleParent, "world")
|
||||||
|
assert getattr(SampleParent, "hello", None) is None
|
||||||
|
assert getattr(SampleParent, "world", None) is None
|
||||||
|
|
||||||
|
monkeypatch.undo()
|
||||||
|
assert original_hello == SampleChild.hello
|
||||||
|
assert original_world == SampleChild.world
|
||||||
|
|
||||||
|
|
||||||
def test_issue1338_name_resolving():
|
def test_issue1338_name_resolving():
|
||||||
pytest.importorskip("requests")
|
pytest.importorskip("requests")
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
|
|
Loading…
Reference in New Issue