Skip to content

Commit

Permalink
Fix mocker.spy for non-function objects in Python 2 (#160)
Browse files Browse the repository at this point in the history
Fix mocker.spy for non-function objects in Python 2
  • Loading branch information
nicoddemus committed Oct 4, 2019
2 parents ca8bed5 + 4a661d5 commit 4c3b469
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 10 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Expand Up @@ -56,7 +56,6 @@ docs/_build/
# Virtual Envs
.env*

_pytest_mock_version.py

# IDE
.idea
/src/pytest_mock/_version.py
10 changes: 10 additions & 0 deletions CHANGELOG.rst
@@ -1,3 +1,13 @@
1.11.1
------

* Fix ``mocker.spy`` on Python 2 when used on non-function objects
which implement ``__call__`` (`#157`_). Thanks `@pbasista`_ for
the report.

.. _#157: https://github.com/pytest-dev/pytest-mock/issues/157
.. _@pbasista: https://github.com/pbasista

1.11.0
------

Expand Down
7 changes: 4 additions & 3 deletions setup.py
@@ -1,15 +1,16 @@
from io import open

from setuptools import setup
from setuptools import setup, find_packages

setup(
name="pytest-mock",
entry_points={"pytest11": ["pytest_mock = pytest_mock"]},
py_modules=["pytest_mock", "_pytest_mock_version"],
packages=find_packages(where="src"),
package_dir={"": "src"},
platforms="any",
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
install_requires=["pytest>=2.7", 'mock;python_version<"3.0"'],
use_scm_version={"write_to": "_pytest_mock_version.py"},
use_scm_version={"write_to": "src/pytest_mock/_version.py"},
setup_requires=["setuptools_scm"],
url="https://github.com/pytest-dev/pytest-mock/",
license="MIT",
Expand Down
2 changes: 2 additions & 0 deletions src/pytest_mock/__init__.py
@@ -0,0 +1,2 @@
from pytest_mock.plugin import *
from pytest_mock.plugin import _get_mock_module
12 changes: 9 additions & 3 deletions pytest_mock.py → src/pytest_mock/plugin.py
@@ -1,12 +1,12 @@
from __future__ import unicode_literals

import functools
import inspect
import sys
from functools import wraps

import pytest

from _pytest_mock_version import version
from ._version import version

__version__ = version

Expand Down Expand Up @@ -105,7 +105,13 @@ def spy(self, obj, name):
if isinstance(value, (classmethod, staticmethod)):
autospec = False

@wraps(method)
if sys.version_info[0] == 2:
assigned = [x for x in functools.WRAPPER_ASSIGNMENTS if hasattr(method, x)]
w = functools.wraps(method, assigned=assigned)
else:
w = functools.wraps(method)

@w
def wrapper(*args, **kwargs):
r = method(*args, **kwargs)
result.return_value = r
Expand Down
20 changes: 20 additions & 0 deletions test_pytest_mock.py → tests/test_pytest_mock.py
Expand Up @@ -366,6 +366,26 @@ class Foo(Base):
assert spy.return_value == 20


def test_callable_like_spy(testdir, mocker):
testdir.makepyfile(
uut="""
class CallLike(object):
def __call__(self, x):
return x * 2
call_like = CallLike()
"""
)
testdir.syspathinsert()

import uut

spy = mocker.spy(uut, "call_like")
uut.call_like(10)
spy.assert_called_once_with(10)
assert spy.return_value == 20


@contextmanager
def assert_traceback():
"""
Expand Down
4 changes: 2 additions & 2 deletions tox.ini
Expand Up @@ -6,11 +6,11 @@ passenv = USER USERNAME
deps =
coverage
commands =
coverage run --append --source=pytest_mock.py -m pytest test_pytest_mock.py
coverage run --append --source={envsitepackagesdir}/pytest_mock -m pytest tests

[testenv:norewrite]
commands =
pytest test_pytest_mock.py --assert=plain
pytest tests --assert=plain

[testenv:linting]
skipsdist = True
Expand Down

0 comments on commit 4c3b469

Please sign in to comment.