Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mocker.spy does not work on non-function objects in Python 2 #157

Closed
pbasista opened this issue Sep 30, 2019 · 1 comment · Fixed by #160
Closed

mocker.spy does not work on non-function objects in Python 2 #157

pbasista opened this issue Sep 30, 2019 · 1 comment · Fixed by #160

Comments

@pbasista
Copy link

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 == 1

In 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.

@nicoddemus
Copy link
Member

Thanks a lot @pbasista for the report, and sorry for the delay.

This has now been fixed in 1.11.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants