From 894db9963f00fc236860907d588c3a079a8d4543 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 4 Oct 2019 18:41:57 -0300 Subject: [PATCH 1/2] Fix mocker.spy on Python 2 for non-functions Fix #157 --- CHANGELOG.rst | 10 ++++++++++ pytest_mock.py | 10 ++++++++-- test_pytest_mock.py | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eec73cb..c85e8fd 100644 --- a/CHANGELOG.rst +++ b/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 ------ diff --git a/pytest_mock.py b/pytest_mock.py index 7d41610..903a240 100644 --- a/pytest_mock.py +++ b/pytest_mock.py @@ -1,8 +1,8 @@ from __future__ import unicode_literals +import functools import inspect import sys -from functools import wraps import pytest @@ -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 diff --git a/test_pytest_mock.py b/test_pytest_mock.py index 4611aba..d3cb832 100644 --- a/test_pytest_mock.py +++ b/test_pytest_mock.py @@ -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(): """ From 4a661d53656cd9935f776f92a6bc2dc3ee97f642 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 4 Oct 2019 18:56:07 -0300 Subject: [PATCH 2/2] Adopt src layout --- .gitignore | 3 +-- setup.py | 7 ++++--- src/pytest_mock/__init__.py | 2 ++ pytest_mock.py => src/pytest_mock/plugin.py | 2 +- test_pytest_mock.py => tests/test_pytest_mock.py | 0 tox.ini | 4 ++-- 6 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 src/pytest_mock/__init__.py rename pytest_mock.py => src/pytest_mock/plugin.py (99%) rename test_pytest_mock.py => tests/test_pytest_mock.py (100%) diff --git a/.gitignore b/.gitignore index 9874ee1..61320c7 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,6 @@ docs/_build/ # Virtual Envs .env* -_pytest_mock_version.py - # IDE .idea +/src/pytest_mock/_version.py diff --git a/setup.py b/setup.py index 714200f..ab24b6c 100644 --- a/setup.py +++ b/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", diff --git a/src/pytest_mock/__init__.py b/src/pytest_mock/__init__.py new file mode 100644 index 0000000..3e2f241 --- /dev/null +++ b/src/pytest_mock/__init__.py @@ -0,0 +1,2 @@ +from pytest_mock.plugin import * +from pytest_mock.plugin import _get_mock_module diff --git a/pytest_mock.py b/src/pytest_mock/plugin.py similarity index 99% rename from pytest_mock.py rename to src/pytest_mock/plugin.py index 903a240..fdf4883 100644 --- a/pytest_mock.py +++ b/src/pytest_mock/plugin.py @@ -6,7 +6,7 @@ import pytest -from _pytest_mock_version import version +from ._version import version __version__ = version diff --git a/test_pytest_mock.py b/tests/test_pytest_mock.py similarity index 100% rename from test_pytest_mock.py rename to tests/test_pytest_mock.py diff --git a/tox.ini b/tox.ini index 98117bf..1911734 100644 --- a/tox.ini +++ b/tox.ini @@ -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