-
-
Notifications
You must be signed in to change notification settings - Fork 152
Description
With pytest-mock version 1.11.0, the non-function objects cannot be spied on using mocker.spy in Python 2. For example:
uut.py:
class A(object):
def __call__(self):
pass
a = A()
def modify_a():
a()test_uut.py:
import uut
def test_modify_a(mocker):
mocker.spy(uut, "a")
uut.modify_a()
uut.a.call_count == 1In Python 2, the test fails with the following exception:
for attr in assigned:
> setattr(wrapper, attr, getattr(wrapped, attr))
E AttributeError: 'A' object has no attribute '__name__'
/usr/lib/python2.7/functools.py:33: AttributeError
The same test works in Python 3. The reason why the behavior is different between Python versions is the different implementation of functools.wraps in Python 2 and Python 3. In Python 3, the attributes which are supposed to be set on the wrapper object but are missing on the original object are simply skipped:
https://github.com/python/cpython/blob/3.7/Lib/functools.py#L52-L58
However, in Python 2, all the attributes which are supposed to be set on the wrapper object must also be present on the original object:
https://github.com/python/cpython/blob/2.7/Lib/functools.py#L32-L33
This prevents the standard call to functools.wraps without extra parameters in Python 2 from being able to wrap the non-function objects that do not have attributes like __name__, which are by default expected to be present on the original (wrapped) object.