diff -Nru pytest-mock-1.7.1/appveyor.yml pytest-mock-1.10.4/appveyor.yml --- pytest-mock-1.7.1/appveyor.yml 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/appveyor.yml 2019-04-17 17:23:43.000000000 +0000 @@ -1,7 +1,10 @@ install: - - C:\Python36\python -m pip install tox + - C:\Python37\python -m pip install -U pip + - C:\Python37\python -m pip install tox build: false # Not a C# project test_script: - - C:\Python36\scripts\tox + - C:\Python37\scripts\tox + +skip_tags: true diff -Nru pytest-mock-1.7.1/CHANGELOG.rst pytest-mock-1.10.4/CHANGELOG.rst --- pytest-mock-1.7.1/CHANGELOG.rst 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/CHANGELOG.rst 2019-04-17 17:23:43.000000000 +0000 @@ -1,3 +1,52 @@ +1.10.4 +------ + +* Fix plugin when 'terminal' plugin is disabled + +1.10.3 +------ + +* Fix test suite in Python 3.8. Thanks `@hroncok`_ for the report and `@blueyed`_ for the PR (`#140`_). + +.. _#140: https://github.com/pytest-dev/pytest-mock/pull/140 +.. _@hroncok: https://github.com/hroncok + +1.10.2 +------ + +* Fix bug at the end of the test session when a call to ``patch.stopall`` is done explicitly by + user code. Thanks `@craiga`_ for the report (`#137`_). + +.. _#137: https://github.com/pytest-dev/pytest-mock/issues/137 +.. _@craiga: https://github.com/craiga + +1.10.1 +------ + +* Fix broken links and update README. Also the code is now formatted using `black `__. + +1.10.0 +------ + +* Add support for the recently added ``assert_called`` method in Python 3.6 and ``mock-2.0``. Thanks `@rouge8`_ for the PR (`#115`_). + +.. _#115: https://github.com/pytest-dev/pytest-mock/pull/115 + +1.9.0 +----- + +* Add support for the recently added ``assert_called_once`` method in Python 3.6 and ``mock-2.0``. Thanks `@rouge8`_ for the PR (`#113`_). + +.. _#113: https://github.com/pytest-dev/pytest-mock/pull/113 + + +1.8.0 +----- + +* Add aliases for ``NonCallableMock`` and ``create_autospec`` to ``mocker``. Thanks `@mlhamel`_ for the PR (`#111`_). + +.. _#111: https://github.com/pytest-dev/pytest-mock/pull/111 + 1.7.1 ----- @@ -300,13 +349,12 @@ .. _#2: https://github.com/pytest-dev/pytest-qt/issues/2 -.. _@mathrick: https://github.com/mathrick -.. _@tigarmo: https://github.com/tigarmo -.. _@rouge8: https://github.com/rouge8 .. _@fogo: https://github.com/fogo +.. _@kmosher: https://github.com/kmosher .. _@marcwebbie: https://github.com/marcwebbie +.. _@mathrick: https://github.com/mathrick +.. _@mlhamel: https://github.com/mlhamel .. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt +.. _@rouge8: https://github.com/rouge8 .. _@The-Compiler: https://github.com/The-Compiler -.. _@kmosher: https://github.com/kmosher - - +.. _@tigarmo: https://github.com/tigarmo diff -Nru pytest-mock-1.7.1/debian/changelog pytest-mock-1.10.4/debian/changelog --- pytest-mock-1.7.1/debian/changelog 2018-03-05 22:45:31.000000000 +0000 +++ pytest-mock-1.10.4/debian/changelog 2019-08-24 16:44:21.000000000 +0000 @@ -1,3 +1,16 @@ +pytest-mock (1.10.4-1) unstable; urgency=medium + + * Team upload. + * New upstream release (Closes: #904304). + * d/control: Remove ancient X-Python3-Version field + * Use debhelper-compat instead of debian/compat. + * Fix compatibility with newer Python, python-mock and pytest + (Closes: #934960). + * Bump standards version to 4.4.0 (no changes). + * Bump debhelper compat level to 12. + + -- Ondřej Nový Sat, 24 Aug 2019 18:44:21 +0200 + pytest-mock (1.7.1-1) unstable; urgency=medium * Team upload @@ -62,4 +75,3 @@ * Initial release. Closes: #801418. -- Vincent Bernat Fri, 09 Oct 2015 23:27:28 +0200 - diff -Nru pytest-mock-1.7.1/debian/compat pytest-mock-1.10.4/debian/compat --- pytest-mock-1.7.1/debian/compat 2018-03-05 22:45:31.000000000 +0000 +++ pytest-mock-1.10.4/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru pytest-mock-1.7.1/debian/control pytest-mock-1.10.4/debian/control --- pytest-mock-1.7.1/debian/control 2018-03-05 22:45:31.000000000 +0000 +++ pytest-mock-1.10.4/debian/control 2019-08-24 16:43:43.000000000 +0000 @@ -3,7 +3,7 @@ Uploaders: Vincent Bernat Section: python Priority: optional -Build-Depends: debhelper (>= 11), +Build-Depends: debhelper-compat (= 12), dh-python, python-all, python-pytest, @@ -15,11 +15,10 @@ python3-setuptools, python3-setuptools-scm Build-Conflicts: python3-mock -Standards-Version: 4.1.3 +Standards-Version: 4.4.0 Vcs-Browser: https://salsa.debian.org/python-team/modules/pytest-mock Vcs-Git: https://salsa.debian.org/python-team/modules/pytest-mock.git Homepage: https://github.com/pytest-dev/pytest-mock/ -X-Python3-Version: >= 3.4 Package: python-pytest-mock Architecture: all diff -Nru pytest-mock-1.7.1/debian/patches/fix-new-mock.patch pytest-mock-1.10.4/debian/patches/fix-new-mock.patch --- pytest-mock-1.7.1/debian/patches/fix-new-mock.patch 1970-01-01 00:00:00.000000000 +0000 +++ pytest-mock-1.10.4/debian/patches/fix-new-mock.patch 2019-08-24 16:36:17.000000000 +0000 @@ -0,0 +1,46 @@ +From b2683fdfc2fbd67dfc14bfc8e9d2c06530975397 Mon Sep 17 00:00:00 2001 +From: Bruno Oliveira +Date: Fri, 3 May 2019 08:58:31 -0300 +Subject: [PATCH] Fix tests due to new formatting in mock 3.0 and python 3.8 + +--- + test_pytest_mock.py | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/test_pytest_mock.py b/test_pytest_mock.py +index 7bc38cb..562ff0c 100644 +--- a/test_pytest_mock.py ++++ b/test_pytest_mock.py +@@ -10,11 +10,11 @@ + + # could not make some of the tests work on PyPy, patches are welcome! + skip_pypy = pytest.mark.skipif( +- platform.python_implementation() == "PyPy", reason="could not make work on pypy" ++ platform.python_implementation() == "PyPy", reason="could not make it work on pypy" + ) + +-# Python 3.8 changed the output formatting (bpo-35500). +-PY38 = sys.version_info >= (3, 8) ++# Python 3.8 changed the output formatting (bpo-35500), which has been ported to mock 3.0 ++NEW_FORMATTING = sys.version_info >= (3, 8) or sys.version_info[0] == 2 + + + @pytest.fixture +@@ -209,7 +209,7 @@ def test_repr_with_name(self, mocker): + + def __test_failure_message(self, mocker, **kwargs): + expected_name = kwargs.get("name") or "mock" +- if PY38: ++ if NEW_FORMATTING: + msg = "expected call not found.\nExpected: {0}()\nActual: not called." + else: + msg = "Expected call: {0}()\nNot called" +@@ -620,7 +620,7 @@ def test(mocker): + """ + ) + result = testdir.runpytest("-s") +- if PY38: ++ if NEW_FORMATTING: + expected_lines = [ + "*AssertionError: expected call not found.", + "*Expected: mock('', bar=4)", diff -Nru pytest-mock-1.7.1/debian/patches/fix-new-pytest.patch pytest-mock-1.10.4/debian/patches/fix-new-pytest.patch --- pytest-mock-1.7.1/debian/patches/fix-new-pytest.patch 1970-01-01 00:00:00.000000000 +0000 +++ pytest-mock-1.10.4/debian/patches/fix-new-pytest.patch 2019-08-24 16:39:18.000000000 +0000 @@ -0,0 +1,46 @@ +From 970e4b1f8cfd6bd750b4c8240efad378cbf049c2 Mon Sep 17 00:00:00 2001 +From: Bruno Oliveira +Date: Mon, 1 Jul 2019 19:31:36 -0300 +Subject: [PATCH] Fix tests expectations with latest pytest + +Fix #149 +--- + test_pytest_mock.py | 2 +- + tox.ini | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/test_pytest_mock.py b/test_pytest_mock.py +index 562ff0c..cdc04fe 100644 +--- a/test_pytest_mock.py ++++ b/test_pytest_mock.py +@@ -639,7 +639,7 @@ def test(mocker): + "*Use -v to get the full diff*", + "*Kwargs:*", + "*assert {} == {'bar': 4}*", +- "*Right contains more items:*", ++ "*Right contains* more item*", + "*{'bar': 4}*", + "*Use -v to get the full diff*", + ] +diff --git a/tox.ini b/tox.ini +index 427b25f..98117bf 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -10,7 +10,7 @@ commands = + + [testenv:norewrite] + commands = +- pytest test_pytest_mock.py --assert=plain -ra ++ pytest test_pytest_mock.py --assert=plain + + [testenv:linting] + skipsdist = True +@@ -20,7 +20,7 @@ basepython = python3.6 + commands = pre-commit run --all-files --show-diff-on-failure + + [pytest] +-addopts = -ra ++addopts = -r a + + [flake8] + max-line-length = 88 diff -Nru pytest-mock-1.7.1/debian/patches/series pytest-mock-1.10.4/debian/patches/series --- pytest-mock-1.7.1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ pytest-mock-1.10.4/debian/patches/series 2019-08-24 16:39:26.000000000 +0000 @@ -0,0 +1,2 @@ +fix-new-mock.patch +fix-new-pytest.patch diff -Nru pytest-mock-1.7.1/HOWTORELEASE.rst pytest-mock-1.10.4/HOWTORELEASE.rst --- pytest-mock-1.7.1/HOWTORELEASE.rst 1970-01-01 00:00:00.000000000 +0000 +++ pytest-mock-1.10.4/HOWTORELEASE.rst 2019-04-17 17:23:43.000000000 +0000 @@ -0,0 +1,7 @@ +Here are the steps on how to make a new release. + +1. Create a ``release-VERSION`` branch from ``upstream/master``. +2. Update ``CHANGELOG.rst``. +3. Push a branch with the changes. +4. Once all builds pass, push a tag to ``upstream``. +5. Merge the PR. diff -Nru pytest-mock-1.7.1/LICENSE pytest-mock-1.10.4/LICENSE --- pytest-mock-1.7.1/LICENSE 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/LICENSE 2019-04-17 17:23:43.000000000 +0000 @@ -18,4 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff -Nru pytest-mock-1.7.1/PKG-INFO pytest-mock-1.10.4/PKG-INFO --- pytest-mock-1.7.1/PKG-INFO 2018-03-01 10:53:25.000000000 +0000 +++ pytest-mock-1.10.4/PKG-INFO 2019-04-17 17:24:00.000000000 +0000 @@ -1,12 +1,11 @@ -Metadata-Version: 1.2 +Metadata-Version: 2.1 Name: pytest-mock -Version: 1.7.1 +Version: 1.10.4 Summary: Thin-wrapper around the mock package for easier use with py.test Home-page: https://github.com/pytest-dev/pytest-mock/ Author: Bruno Oliveira Author-email: nicoddemus@gmail.com License: MIT -Description-Content-Type: UNKNOWN Description: =========== pytest-mock =========== @@ -19,27 +18,26 @@ .. code-block:: python import os - + class UnixFS: - + @staticmethod def rm(filename): os.remove(filename) - + def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') - .. Using PNG badges because PyPI doesn't support SVG - |python| |version| |anaconda| |ci| |appveyor| |coverage| + |python| |version| |anaconda| |ci| |appveyor| |coverage| |black| .. |version| image:: http://img.shields.io/pypi/v/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock - .. |anaconda| image:: https://anaconda.org/conda-forge/pytest-mock/badges/version.svg + .. |anaconda| image:: https://img.shields.io/conda/vn/conda-forge/pytest-mock.svg :target: https://anaconda.org/conda-forge/pytest-mock .. |ci| image:: http://img.shields.io/travis/pytest-dev/pytest-mock.svg @@ -53,19 +51,17 @@ .. |python| image:: https://img.shields.io/pypi/pyversions/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock/ - - - .. image:: http://www.opensourcecitizen.org/badge?url=github.com/pytest-dev/pytest-mock - :target: http://www.opensourcecitizen.org/project?url=github.com/pytest-dev/pytest-mock - If you found this library useful, donate some CPU cycles to its - development efforts by clicking above. Thank you! 😇 + .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/ambv/black + + `Professionally supported pytest-mock is now available `_ Usage ===== The ``mocker`` fixture has the same API as - `mock.patch `_, + `mock.patch `_, supporting the same arguments: .. code-block:: python @@ -78,14 +74,14 @@ The supported methods are: - * ``mocker.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch. - * ``mocker.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. - * ``mocker.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. - * ``mocker.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. - * ``mocker.stopall()``: stops all active patches up to this point. - * ``mocker.resetall()``: calls ``reset_mock()`` in all mocked objects up to this point. + * `mocker.patch `_ + * `mocker.patch.object `_ + * `mocker.patch.multiple `_ + * `mocker.patch.dict `_ + * `mocker.stopall `_ + * ``mocker.resetall()``: calls `reset_mock() `_ in all mocked objects up to this point. - Some objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: + These objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: * `Mock `_ * `MagicMock `_ @@ -169,8 +165,8 @@ E Right contains more items: E {'bar': 4} E Use -v to get the full diff - - + + test_foo.py:6: AssertionError ========================== 1 failed in 0.03 seconds =========================== @@ -331,6 +327,26 @@ return my_cm + Contributing + ============ + + Contributions are welcome! After cloning the repository, create a virtual env + and install ``pytest-mock`` in editable mode with ``dev`` extras: + + .. code-block:: console + + $ pip install --editable .[dev] + $ pre-commit install + + Tests are run with ``tox``, you can run the baseline environments before submitting a PR: + + .. code-block:: console + + $ tox -e py27,py36,linting + + Style checks and formatting are done automatically during commit courtesy of + `pre-commit `_. + License ======= @@ -351,5 +367,8 @@ Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Software Development :: Testing Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Provides-Extra: dev diff -Nru pytest-mock-1.7.1/.pre-commit-config.yaml pytest-mock-1.10.4/.pre-commit-config.yaml --- pytest-mock-1.7.1/.pre-commit-config.yaml 1970-01-01 00:00:00.000000000 +0000 +++ pytest-mock-1.10.4/.pre-commit-config.yaml 2019-04-17 17:23:43.000000000 +0000 @@ -0,0 +1,22 @@ +exclude: '^($|.*\.bin)' +repos: + - repo: https://github.com/ambv/black + rev: 18.6b4 + hooks: + - id: black + args: [--safe, --quiet] + language_version: python3.6 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v1.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - repo: local + hooks: + - id: rst + name: rst + entry: rst-lint --encoding utf-8 + files: ^(CHANGELOG.rst|README.rst|HOWTORELEASE.rst|changelog/.*)$ + language: python + additional_dependencies: [pygments, restructuredtext_lint] + python_version: python3.6 diff -Nru pytest-mock-1.7.1/pytest_mock.egg-info/PKG-INFO pytest-mock-1.10.4/pytest_mock.egg-info/PKG-INFO --- pytest-mock-1.7.1/pytest_mock.egg-info/PKG-INFO 2018-03-01 10:53:25.000000000 +0000 +++ pytest-mock-1.10.4/pytest_mock.egg-info/PKG-INFO 2019-04-17 17:23:59.000000000 +0000 @@ -1,12 +1,11 @@ -Metadata-Version: 1.2 +Metadata-Version: 2.1 Name: pytest-mock -Version: 1.7.1 +Version: 1.10.4 Summary: Thin-wrapper around the mock package for easier use with py.test Home-page: https://github.com/pytest-dev/pytest-mock/ Author: Bruno Oliveira Author-email: nicoddemus@gmail.com License: MIT -Description-Content-Type: UNKNOWN Description: =========== pytest-mock =========== @@ -19,27 +18,26 @@ .. code-block:: python import os - + class UnixFS: - + @staticmethod def rm(filename): os.remove(filename) - + def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') - .. Using PNG badges because PyPI doesn't support SVG - |python| |version| |anaconda| |ci| |appveyor| |coverage| + |python| |version| |anaconda| |ci| |appveyor| |coverage| |black| .. |version| image:: http://img.shields.io/pypi/v/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock - .. |anaconda| image:: https://anaconda.org/conda-forge/pytest-mock/badges/version.svg + .. |anaconda| image:: https://img.shields.io/conda/vn/conda-forge/pytest-mock.svg :target: https://anaconda.org/conda-forge/pytest-mock .. |ci| image:: http://img.shields.io/travis/pytest-dev/pytest-mock.svg @@ -53,19 +51,17 @@ .. |python| image:: https://img.shields.io/pypi/pyversions/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock/ - - - .. image:: http://www.opensourcecitizen.org/badge?url=github.com/pytest-dev/pytest-mock - :target: http://www.opensourcecitizen.org/project?url=github.com/pytest-dev/pytest-mock - If you found this library useful, donate some CPU cycles to its - development efforts by clicking above. Thank you! 😇 + .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/ambv/black + + `Professionally supported pytest-mock is now available `_ Usage ===== The ``mocker`` fixture has the same API as - `mock.patch `_, + `mock.patch `_, supporting the same arguments: .. code-block:: python @@ -78,14 +74,14 @@ The supported methods are: - * ``mocker.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch. - * ``mocker.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. - * ``mocker.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. - * ``mocker.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. - * ``mocker.stopall()``: stops all active patches up to this point. - * ``mocker.resetall()``: calls ``reset_mock()`` in all mocked objects up to this point. + * `mocker.patch `_ + * `mocker.patch.object `_ + * `mocker.patch.multiple `_ + * `mocker.patch.dict `_ + * `mocker.stopall `_ + * ``mocker.resetall()``: calls `reset_mock() `_ in all mocked objects up to this point. - Some objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: + These objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: * `Mock `_ * `MagicMock `_ @@ -169,8 +165,8 @@ E Right contains more items: E {'bar': 4} E Use -v to get the full diff - - + + test_foo.py:6: AssertionError ========================== 1 failed in 0.03 seconds =========================== @@ -331,6 +327,26 @@ return my_cm + Contributing + ============ + + Contributions are welcome! After cloning the repository, create a virtual env + and install ``pytest-mock`` in editable mode with ``dev`` extras: + + .. code-block:: console + + $ pip install --editable .[dev] + $ pre-commit install + + Tests are run with ``tox``, you can run the baseline environments before submitting a PR: + + .. code-block:: console + + $ tox -e py27,py36,linting + + Style checks and formatting are done automatically during commit courtesy of + `pre-commit `_. + License ======= @@ -351,5 +367,8 @@ Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Software Development :: Testing Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Provides-Extra: dev diff -Nru pytest-mock-1.7.1/pytest_mock.egg-info/requires.txt pytest-mock-1.10.4/pytest_mock.egg-info/requires.txt --- pytest-mock-1.7.1/pytest_mock.egg-info/requires.txt 2018-03-01 10:53:25.000000000 +0000 +++ pytest-mock-1.10.4/pytest_mock.egg-info/requires.txt 2019-04-17 17:23:59.000000000 +0000 @@ -2,3 +2,7 @@ [:python_version < "3.0"] mock + +[dev] +pre-commit +tox diff -Nru pytest-mock-1.7.1/pytest_mock.egg-info/SOURCES.txt pytest-mock-1.10.4/pytest_mock.egg-info/SOURCES.txt --- pytest-mock-1.7.1/pytest_mock.egg-info/SOURCES.txt 2018-03-01 10:53:25.000000000 +0000 +++ pytest-mock-1.10.4/pytest_mock.egg-info/SOURCES.txt 2019-04-17 17:23:59.000000000 +0000 @@ -1,6 +1,8 @@ .gitignore +.pre-commit-config.yaml .travis.yml CHANGELOG.rst +HOWTORELEASE.rst LICENSE README.rst _pytest_mock_version.py diff -Nru pytest-mock-1.7.1/pytest_mock.py pytest-mock-1.10.4/pytest_mock.py --- pytest-mock-1.7.1/pytest_mock.py 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/pytest_mock.py 2019-04-17 17:23:43.000000000 +0000 @@ -22,13 +22,17 @@ "unittest.mock" for Python 3, but the user can force to always use "mock" on Python 3 using the mock_use_standalone_module ini option. """ - if not hasattr(_get_mock_module, '_module'): - use_standalone_module = parse_ini_boolean(config.getini('mock_use_standalone_module')) + if not hasattr(_get_mock_module, "_module"): + use_standalone_module = parse_ini_boolean( + config.getini("mock_use_standalone_module") + ) if sys.version_info[0] == 2 or use_standalone_module: import mock + _get_mock_module._module = mock else: import unittest.mock + _get_mock_module._module = unittest.mock return _get_mock_module._module @@ -48,10 +52,12 @@ # aliases for convenience self.Mock = mock_module.Mock self.MagicMock = mock_module.MagicMock + self.NonCallableMock = mock_module.NonCallableMock self.PropertyMock = mock_module.PropertyMock self.call = mock_module.call self.ANY = mock_module.ANY self.DEFAULT = mock_module.DEFAULT + self.create_autospec = mock_module.create_autospec self.sentinel = mock_module.sentinel self.mock_open = mock_module.mock_open @@ -98,8 +104,7 @@ if isinstance(value, (classmethod, staticmethod)): autospec = False - result = self.patch.object(obj, name, side_effect=method, - autospec=autospec) + result = self.patch.object(obj, name, side_effect=method, autospec=autospec) return result def stub(self, name=None): @@ -132,7 +137,7 @@ p = mock_func(*args, **kwargs) mocked = p.start() self._patches.append(p) - if hasattr(mocked, 'reset_mock'): + if hasattr(mocked, "reset_mock"): self._mocks.append(mocked) return mocked @@ -142,8 +147,7 @@ def multiple(self, *args, **kwargs): """API to mock.patch.multiple""" - return self._start_patch(self.mock_module.patch.multiple, *args, - **kwargs) + return self._start_patch(self.mock_module.patch.multiple, *args, **kwargs) def dict(self, *args, **kwargs): """API to mock.patch.dict""" @@ -171,8 +175,10 @@ Same as "mocker", but kept only for backward compatibility. """ import warnings - warnings.warn('"mock" fixture has been deprecated, use "mocker" instead', - DeprecationWarning) + + warnings.warn( + '"mock" fixture has been deprecated, use "mocker" instead', DeprecationWarning + ) return mocker @@ -186,22 +192,22 @@ __wrapped_mock_method__(*args, **kwargs) return except AssertionError as e: - if getattr(e, '_mock_introspection_applied', 0): + if getattr(e, "_mock_introspection_applied", 0): msg = text_type(e) else: __mock_self = args[0] msg = text_type(e) if __mock_self.call_args is not None: actual_args, actual_kwargs = __mock_self.call_args - msg += '\n\npytest introspection follows:\n' + msg += "\n\npytest introspection follows:\n" try: assert actual_args == args[1:] except AssertionError as e: - msg += '\nArgs:\n' + text_type(e) + msg += "\nArgs:\n" + text_type(e) try: assert actual_kwargs == kwargs except AssertionError as e: - msg += '\nKwargs:\n' + text_type(e) + msg += "\nKwargs:\n" + text_type(e) e = AssertionError(msg) e._mock_introspection_applied = True raise e @@ -209,32 +215,37 @@ def wrap_assert_not_called(*args, **kwargs): __tracebackhide__ = True - assert_wrapper(_mock_module_originals["assert_not_called"], - *args, **kwargs) + assert_wrapper(_mock_module_originals["assert_not_called"], *args, **kwargs) def wrap_assert_called_with(*args, **kwargs): __tracebackhide__ = True - assert_wrapper(_mock_module_originals["assert_called_with"], - *args, **kwargs) + assert_wrapper(_mock_module_originals["assert_called_with"], *args, **kwargs) + + +def wrap_assert_called_once(*args, **kwargs): + __tracebackhide__ = True + assert_wrapper(_mock_module_originals["assert_called_once"], *args, **kwargs) def wrap_assert_called_once_with(*args, **kwargs): __tracebackhide__ = True - assert_wrapper(_mock_module_originals["assert_called_once_with"], - *args, **kwargs) + assert_wrapper(_mock_module_originals["assert_called_once_with"], *args, **kwargs) def wrap_assert_has_calls(*args, **kwargs): __tracebackhide__ = True - assert_wrapper(_mock_module_originals["assert_has_calls"], - *args, **kwargs) + assert_wrapper(_mock_module_originals["assert_has_calls"], *args, **kwargs) def wrap_assert_any_call(*args, **kwargs): __tracebackhide__ = True - assert_wrapper(_mock_module_originals["assert_any_call"], - *args, **kwargs) + assert_wrapper(_mock_module_originals["assert_any_call"], *args, **kwargs) + + +def wrap_assert_called(*args, **kwargs): + __tracebackhide__ = True + assert_wrapper(_mock_module_originals["assert_called"], *args, **kwargs) def wrap_assert_methods(config): @@ -249,11 +260,13 @@ mock_module = _get_mock_module(config) wrappers = { - 'assert_not_called': wrap_assert_not_called, - 'assert_called_with': wrap_assert_called_with, - 'assert_called_once_with': wrap_assert_called_once_with, - 'assert_has_calls': wrap_assert_has_calls, - 'assert_any_call': wrap_assert_any_call, + "assert_called": wrap_assert_called, + "assert_called_once": wrap_assert_called_once, + "assert_called_with": wrap_assert_called_with, + "assert_called_once_with": wrap_assert_called_once_with, + "assert_any_call": wrap_assert_any_call, + "assert_has_calls": wrap_assert_has_calls, + "assert_not_called": wrap_assert_not_called, } for method, wrapper in wrappers.items(): try: @@ -261,12 +274,11 @@ except AttributeError: # pragma: no cover continue _mock_module_originals[method] = original - patcher = mock_module.patch.object( - mock_module.NonCallableMock, method, wrapper) + patcher = mock_module.patch.object(mock_module.NonCallableMock, method, wrapper) patcher.start() _mock_module_patches.append(patcher) - if hasattr(config, 'add_cleanup'): + if hasattr(config, "add_cleanup"): add_cleanup = config.add_cleanup else: # pytest 2.7 compatibility @@ -276,32 +288,49 @@ def unwrap_assert_methods(): for patcher in _mock_module_patches: - patcher.stop() + try: + patcher.stop() + except RuntimeError as e: + # a patcher might have been stopped by user code (#137) + # so we need to catch this error here and ignore it; + # unfortunately there's no public API to check if a patch + # has been started, so catching the error it is + if text_type(e) == "stop called on unstarted patcher": + pass + else: + raise _mock_module_patches[:] = [] _mock_module_originals.clear() def pytest_addoption(parser): - parser.addini('mock_traceback_monkeypatch', - 'Monkeypatch the mock library to improve reporting of the ' - 'assert_called_... methods', - default=True) - parser.addini('mock_use_standalone_module', - 'Use standalone "mock" (from PyPI) instead of builtin "unittest.mock" ' - 'on Python 3', - default=False) + parser.addini( + "mock_traceback_monkeypatch", + "Monkeypatch the mock library to improve reporting of the " + "assert_called_... methods", + default=True, + ) + parser.addini( + "mock_use_standalone_module", + 'Use standalone "mock" (from PyPI) instead of builtin "unittest.mock" ' + "on Python 3", + default=False, + ) def parse_ini_boolean(value): if value in (True, False): return value try: - return {'true': True, 'false': False}[value.lower()] + return {"true": True, "false": False}[value.lower()] except KeyError: - raise ValueError('unknown string for bool: %r' % value) + raise ValueError("unknown string for bool: %r" % value) def pytest_configure(config): - tb = config.getoption('--tb') - if parse_ini_boolean(config.getini('mock_traceback_monkeypatch')) and tb != 'native': + tb = config.getoption("--tb", default="auto") + if ( + parse_ini_boolean(config.getini("mock_traceback_monkeypatch")) + and tb != "native" + ): wrap_assert_methods(config) diff -Nru pytest-mock-1.7.1/_pytest_mock_version.py pytest-mock-1.10.4/_pytest_mock_version.py --- pytest-mock-1.7.1/_pytest_mock_version.py 2018-03-01 10:53:25.000000000 +0000 +++ pytest-mock-1.10.4/_pytest_mock_version.py 2019-04-17 17:23:59.000000000 +0000 @@ -1,4 +1,4 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '1.7.1' +version = '1.10.4' diff -Nru pytest-mock-1.7.1/README.rst pytest-mock-1.10.4/README.rst --- pytest-mock-1.7.1/README.rst 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/README.rst 2019-04-17 17:23:43.000000000 +0000 @@ -10,27 +10,26 @@ .. code-block:: python import os - + class UnixFS: - + @staticmethod def rm(filename): os.remove(filename) - + def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') -.. Using PNG badges because PyPI doesn't support SVG -|python| |version| |anaconda| |ci| |appveyor| |coverage| +|python| |version| |anaconda| |ci| |appveyor| |coverage| |black| .. |version| image:: http://img.shields.io/pypi/v/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock -.. |anaconda| image:: https://anaconda.org/conda-forge/pytest-mock/badges/version.svg +.. |anaconda| image:: https://img.shields.io/conda/vn/conda-forge/pytest-mock.svg :target: https://anaconda.org/conda-forge/pytest-mock .. |ci| image:: http://img.shields.io/travis/pytest-dev/pytest-mock.svg @@ -44,19 +43,17 @@ .. |python| image:: https://img.shields.io/pypi/pyversions/pytest-mock.svg :target: https://pypi.python.org/pypi/pytest-mock/ - - -.. image:: http://www.opensourcecitizen.org/badge?url=github.com/pytest-dev/pytest-mock - :target: http://www.opensourcecitizen.org/project?url=github.com/pytest-dev/pytest-mock -If you found this library useful, donate some CPU cycles to its -development efforts by clicking above. Thank you! 😇 +.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/ambv/black + +`Professionally supported pytest-mock is now available `_ Usage ===== The ``mocker`` fixture has the same API as -`mock.patch `_, +`mock.patch `_, supporting the same arguments: .. code-block:: python @@ -69,14 +66,14 @@ The supported methods are: -* ``mocker.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch. -* ``mocker.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. -* ``mocker.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. -* ``mocker.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. -* ``mocker.stopall()``: stops all active patches up to this point. -* ``mocker.resetall()``: calls ``reset_mock()`` in all mocked objects up to this point. +* `mocker.patch `_ +* `mocker.patch.object `_ +* `mocker.patch.multiple `_ +* `mocker.patch.dict `_ +* `mocker.stopall `_ +* ``mocker.resetall()``: calls `reset_mock() `_ in all mocked objects up to this point. -Some objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: +These objects from the ``mock`` module are accessible directly from ``mocker`` for convenience: * `Mock `_ * `MagicMock `_ @@ -160,8 +157,8 @@ E Right contains more items: E {'bar': 4} E Use -v to get the full diff - - + + test_foo.py:6: AssertionError ========================== 1 failed in 0.03 seconds =========================== @@ -322,6 +319,26 @@ return my_cm +Contributing +============ + +Contributions are welcome! After cloning the repository, create a virtual env +and install ``pytest-mock`` in editable mode with ``dev`` extras: + +.. code-block:: console + + $ pip install --editable .[dev] + $ pre-commit install + +Tests are run with ``tox``, you can run the baseline environments before submitting a PR: + +.. code-block:: console + + $ tox -e py27,py36,linting + +Style checks and formatting are done automatically during commit courtesy of +`pre-commit `_. + License ======= diff -Nru pytest-mock-1.7.1/setup.py pytest-mock-1.10.4/setup.py --- pytest-mock-1.7.1/setup.py 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/setup.py 2019-04-17 17:23:43.000000000 +0000 @@ -1,40 +1,38 @@ -from setuptools import setup - from io import open +from setuptools import setup + setup( - name='pytest-mock', - entry_points={ - 'pytest11': ['pytest_mock = pytest_mock'], - }, - py_modules=['pytest_mock', '_pytest_mock_version'], - 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'}, - setup_requires=['setuptools_scm'], - url='https://github.com/pytest-dev/pytest-mock/', - license='MIT', - author='Bruno Oliveira', - author_email='nicoddemus@gmail.com', - description='Thin-wrapper around the mock package for easier use with py.test', - long_description=open('README.rst', encoding='utf-8').read(), + name="pytest-mock", + entry_points={"pytest11": ["pytest_mock = pytest_mock"]}, + py_modules=["pytest_mock", "_pytest_mock_version"], + 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"}, + setup_requires=["setuptools_scm"], + url="https://github.com/pytest-dev/pytest-mock/", + license="MIT", + author="Bruno Oliveira", + author_email="nicoddemus@gmail.com", + description="Thin-wrapper around the mock package for easier use with py.test", + long_description=open("README.rst", encoding="utf-8").read(), keywords="pytest mock", + extras_require={"dev": ["pre-commit", "tox"]}, classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Framework :: Pytest', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Topic :: Software Development :: Testing', - ] + "Development Status :: 5 - Production/Stable", + "Framework :: Pytest", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Topic :: Software Development :: Testing", + ], ) diff -Nru pytest-mock-1.7.1/test_pytest_mock.py pytest-mock-1.10.4/test_pytest_mock.py --- pytest-mock-1.7.1/test_pytest_mock.py 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/test_pytest_mock.py 2019-04-17 17:23:43.000000000 +0000 @@ -6,11 +6,15 @@ import py.code import pytest -pytest_plugins = 'pytester' +pytest_plugins = "pytester" # could not make some of the tests work on PyPy, patches are welcome! -skip_pypy = pytest.mark.skipif(platform.python_implementation() == 'PyPy', - reason='could not make work on pypy') +skip_pypy = pytest.mark.skipif( + platform.python_implementation() == "PyPy", reason="could not make work on pypy" +) + +# Python 3.8 changed the output formatting (bpo-35500). +PY38 = sys.version_info >= (3, 8) @pytest.fixture @@ -20,10 +24,12 @@ Making this a fixture to avoid acessing pytest's config in the global context. """ - option = pytestconfig.getoption('assertmode') - if option != 'rewrite': - pytest.skip('this test needs assertion rewrite to work but current option ' - 'is "{}"'.format(option)) + option = pytestconfig.getoption("assertmode") + if option != "rewrite": + pytest.skip( + "this test needs assertion rewrite to work but current option " + 'is "{}"'.format(option) + ) class UnixFS(object): @@ -52,20 +58,20 @@ assert mocked_rm is os.remove assert mocked_ls is os.listdir - file_name = tmpdir / 'foo.txt' + file_name = tmpdir / "foo.txt" file_name.ensure() UnixFS.rm(str(file_name)) mocked_rm.assert_called_once_with(str(file_name)) assert os.path.isfile(str(file_name)) - mocked_ls.return_value = ['bar.txt'] - assert UnixFS.ls(str(tmpdir)) == ['bar.txt'] + mocked_ls.return_value = ["bar.txt"] + assert UnixFS.ls(str(tmpdir)) == ["bar.txt"] mocked_ls.assert_called_once_with(str(tmpdir)) mocker.stopall() - assert UnixFS.ls(str(tmpdir)) == ['foo.txt'] + assert UnixFS.ls(str(tmpdir)) == ["foo.txt"] UnixFS.rm(str(file_name)) assert not os.path.isfile(str(file_name)) @@ -73,21 +79,20 @@ def mock_using_patch_object(mocker): - return mocker.patch.object(os, 'remove'), mocker.patch.object(os, 'listdir') + return mocker.patch.object(os, "remove"), mocker.patch.object(os, "listdir") def mock_using_patch(mocker): - return mocker.patch('os.remove'), mocker.patch('os.listdir') + return mocker.patch("os.remove"), mocker.patch("os.listdir") def mock_using_patch_multiple(mocker): - r = mocker.patch.multiple('os', remove=mocker.DEFAULT, - listdir=mocker.DEFAULT) - return r['remove'], r['listdir'] + r = mocker.patch.multiple("os", remove=mocker.DEFAULT, listdir=mocker.DEFAULT) + return r["remove"], r["listdir"] -@pytest.mark.parametrize('mock_fs', [mock_using_patch_object, mock_using_patch, - mock_using_patch_multiple], +@pytest.mark.parametrize( + "mock_fs", [mock_using_patch_object, mock_using_patch, mock_using_patch_multiple] ) def test_mock_patches(mock_fs, mocker, check_unix_fs_mocked): """ @@ -108,11 +113,11 @@ Testing :param mock: """ - x = {'original': 1} - mocker.patch.dict(x, values=[('new', 10)], clear=True) - assert x == {'new': 10} + x = {"original": 1} + mocker.patch.dict(x, values=[("new", 10)], clear=True) + assert x == {"new": 10} mocker.stopall() - assert x == {'original': 1} + assert x == {"original": 1} def test_mock_patch_dict_resetall(mocker): @@ -120,24 +125,49 @@ We can call resetall after patching a dict. :param mock: """ - x = {'original': 1} - mocker.patch.dict(x, values=[('new', 10)], clear=True) - assert x == {'new': 10} + x = {"original": 1} + mocker.patch.dict(x, values=[("new", 10)], clear=True) + assert x == {"new": 10} mocker.resetall() - assert x == {'new': 10} + assert x == {"new": 10} -def test_deprecated_mock(mock, tmpdir): +def test_deprecated_mock(testdir): """ Use backward-compatibility-only mock fixture to ensure complete coverage. """ - mock.patch('os.listdir', return_value=['mocked']) - assert os.listdir(str(tmpdir)) == ['mocked'] - mock.stopall() - assert os.listdir(str(tmpdir)) == [] + p1 = testdir.makepyfile( + """ + import os + + def test(mock, tmpdir): + mock.patch("os.listdir", return_value=["mocked"]) + assert os.listdir(str(tmpdir)) == ["mocked"] + mock.stopall() + assert os.listdir(str(tmpdir)) == [] + """ + ) + result = testdir.runpytest(str(p1)) + result.stdout.fnmatch_lines( + ['*DeprecationWarning: "mock" fixture has been deprecated, use "mocker"*'] + ) + assert result.ret == 0 -@pytest.mark.parametrize('name', ['MagicMock', 'PropertyMock', 'Mock', 'call', 'ANY', 'sentinel', 'mock_open']) +@pytest.mark.parametrize( + "name", + [ + "ANY", + "call", + "create_autospec", + "MagicMock", + "Mock", + "mock_open", + "NonCallableMock", + "PropertyMock", + "sentinel", + ], +) def test_mocker_aliases(name, pytestconfig): from pytest_mock import _get_mock_module, MockFixture @@ -148,8 +178,8 @@ def test_mocker_resetall(mocker): - listdir = mocker.patch('os.listdir') - open = mocker.patch('os.open') + listdir = mocker.patch("os.listdir") + open = mocker.patch("os.open") listdir("/tmp") open("/tmp/foo.txt") @@ -165,21 +195,25 @@ class TestMockerStub: def test_call(self, mocker): stub = mocker.stub() - stub('foo', 'bar') - stub.assert_called_once_with('foo', 'bar') + stub("foo", "bar") + stub.assert_called_once_with("foo", "bar") def test_repr_with_no_name(self, mocker): stub = mocker.stub() - assert not 'name' in repr(stub) + assert "name" not in repr(stub) def test_repr_with_name(self, mocker): - test_name = 'funny walk' + test_name = "funny walk" stub = mocker.stub(name=test_name) assert "name={0!r}".format(test_name) in repr(stub) def __test_failure_message(self, mocker, **kwargs): - expected_name = kwargs.get('name') or 'mock' - expected_message = 'Expected call: {0}()\nNot called'.format(expected_name) + expected_name = kwargs.get("name") or "mock" + if PY38: + msg = "expected call not found.\nExpected: {0}()\nActual: not called." + else: + msg = "Expected call: {0}()\nNot called" + expected_message = msg.format(expected_name) stub = mocker.stub(**kwargs) with pytest.raises(AssertionError) as exc_info: stub.assert_called_with() @@ -188,20 +222,19 @@ def test_failure_message_with_no_name(self, mocker): self.__test_failure_message(mocker) - @pytest.mark.parametrize('name', (None, '', 'f', 'The Castle of aaarrrrggh')) + @pytest.mark.parametrize("name", (None, "", "f", "The Castle of aaarrrrggh")) def test_failure_message_with_name(self, mocker, name): self.__test_failure_message(mocker, name=name) def test_instance_method_spy(mocker): class Foo(object): - def bar(self, arg): return arg * 2 foo = Foo() other = Foo() - spy = mocker.spy(foo, 'bar') + spy = mocker.spy(foo, "bar") assert foo.bar(arg=10) == 20 assert other.bar(arg=10) == 20 foo.bar.assert_called_once_with(arg=10) @@ -211,11 +244,10 @@ @skip_pypy def test_instance_method_by_class_spy(mocker): class Foo(object): - def bar(self, arg): return arg * 2 - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") foo = Foo() other = Foo() assert foo.bar(arg=10) == 20 @@ -226,16 +258,14 @@ @skip_pypy def test_instance_method_by_subclass_spy(mocker): - class Base(object): - def bar(self, arg): return arg * 2 class Foo(Base): pass - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") foo = Foo() other = Foo() assert foo.bar(arg=10) == 20 @@ -247,22 +277,20 @@ @skip_pypy def test_class_method_spy(mocker): class Foo(object): - @classmethod def bar(cls, arg): return arg * 2 - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) spy.assert_called_once_with(arg=10) @skip_pypy -@pytest.mark.xfail(sys.version_info[0] == 2, reason='does not work on Python 2') +@pytest.mark.xfail(sys.version_info[0] == 2, reason="does not work on Python 2") def test_class_method_subclass_spy(mocker): class Base(object): - @classmethod def bar(self, arg): return arg * 2 @@ -270,7 +298,7 @@ class Foo(Base): pass - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) spy.assert_called_once_with(arg=10) @@ -289,7 +317,7 @@ def bar(cls, arg): return arg * 2 - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) spy.assert_called_once_with(arg=10) @@ -298,22 +326,20 @@ @skip_pypy def test_static_method_spy(mocker): class Foo(object): - @staticmethod def bar(arg): return arg * 2 - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) spy.assert_called_once_with(arg=10) @skip_pypy -@pytest.mark.xfail(sys.version_info[0] == 2, reason='does not work on Python 2') +@pytest.mark.xfail(sys.version_info[0] == 2, reason="does not work on Python 2") def test_static_method_subclass_spy(mocker): class Base(object): - @staticmethod def bar(arg): return arg * 2 @@ -321,7 +347,7 @@ class Foo(Base): pass - spy = mocker.spy(Foo, 'bar') + spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) spy.assert_called_once_with(arg=10) @@ -352,17 +378,20 @@ except AssertionError as e: # this may be a bit too assuming, but seems nicer then hard-coding import _pytest.assertion.util as util + # NOTE: we assert with either verbose or not, depending on how our own # test was run by examining sys.argv - verbose = any(a.startswith('-v') for a in sys.argv) - expected = '\n '.join(util._compare_eq_iterable(left, right, verbose)) + verbose = any(a.startswith("-v") for a in sys.argv) + expected = "\n ".join(util._compare_eq_iterable(left, right, verbose)) assert expected in str(e) else: raise AssertionError("DID NOT RAISE") -@pytest.mark.skipif(sys.version_info[:2] == (3, 4), - reason="assert_not_called not available in Python 3.4") +@pytest.mark.skipif( + sys.version_info[:2] == (3, 4), + reason="assert_not_called not available in Python 3.4", +) def test_assert_not_called_wrapper(mocker): stub = mocker.stub() stub.assert_not_called() @@ -388,12 +417,35 @@ stub.assert_called_once_with("foo") -@pytest.mark.usefixtures('needs_assert_rewrite') +def test_assert_called_once_wrapper(mocker): + stub = mocker.stub() + if not hasattr(stub, "assert_called_once"): + pytest.skip("assert_called_once not available") + stub("foo") + stub.assert_called_once() + stub("foo") + with assert_traceback(): + stub.assert_called_once() + + +def test_assert_called_wrapper(mocker): + stub = mocker.stub() + if not hasattr(stub, "assert_called"): + pytest.skip("assert_called_once not available") + with assert_traceback(): + stub.assert_called() + stub("foo") + stub.assert_called() + stub("foo") + stub.assert_called() + + +@pytest.mark.usefixtures("needs_assert_rewrite") def test_assert_called_args_with_introspection(mocker): stub = mocker.stub() - complex_args = ('a', 1, set(['test'])) - wrong_args = ('b', 2, set(['jest'])) + complex_args = ("a", 1, set(["test"])) + wrong_args = ("b", 2, set(["jest"])) stub(*complex_args) stub.assert_called_with(*complex_args) @@ -404,12 +456,12 @@ stub.assert_called_once_with(*wrong_args) -@pytest.mark.usefixtures('needs_assert_rewrite') +@pytest.mark.usefixtures("needs_assert_rewrite") def test_assert_called_kwargs_with_introspection(mocker): stub = mocker.stub() - complex_kwargs = dict(foo={'bar': 1, 'baz': 'spam'}) - wrong_kwargs = dict(foo={'goo': 1, 'baz': 'bran'}) + complex_kwargs = dict(foo={"bar": 1, "baz": "spam"}) + wrong_kwargs = dict(foo={"goo": 1, "baz": "bran"}) stub(**complex_kwargs) stub.assert_called_with(**complex_kwargs) @@ -442,26 +494,31 @@ stub = mocker.stub() assert stub.assert_called_with.__module__ != stub.__module__ - testdir.makepyfile(""" + testdir.makepyfile( + """ import py.code def test_foo(mocker): stub = mocker.stub() assert stub.assert_called_with.__module__ == stub.__module__ - """) - testdir.makeini(""" + """ + ) + testdir.makeini( + """ [pytest] mock_traceback_monkeypatch = false - """) + """ + ) result = runpytest_subprocess(testdir) assert result.ret == 0 def test_parse_ini_boolean(): import pytest_mock - assert pytest_mock.parse_ini_boolean('True') is True - assert pytest_mock.parse_ini_boolean('false') is False + + assert pytest_mock.parse_ini_boolean("True") is True + assert pytest_mock.parse_ini_boolean("false") is False with pytest.raises(ValueError): - pytest_mock.parse_ini_boolean('foo') + pytest_mock.parse_ini_boolean("foo") def test_patched_method_parameter_name(mocker): @@ -474,73 +531,109 @@ def request(cls, method, args): pass - m = mocker.patch.object(Request, 'request') - Request.request(method='get', args={'type': 'application/json'}) - m.assert_called_once_with(method='get', args={'type': 'application/json'}) + m = mocker.patch.object(Request, "request") + Request.request(method="get", args={"type": "application/json"}) + m.assert_called_once_with(method="get", args={"type": "application/json"}) def test_monkeypatch_native(testdir): """Automatically disable monkeypatching when --tb=native. """ - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_foo(mocker): stub = mocker.stub() stub(1, greet='hello') stub.assert_called_once_with(1, greet='hey') - """) - result = runpytest_subprocess(testdir, '--tb=native') + """ + ) + result = runpytest_subprocess(testdir, "--tb=native") assert result.ret == 1 - assert 'During handling of the above exception' not in result.stdout.str() - assert 'Differing items:' not in result.stdout.str() - traceback_lines = [x for x in result.stdout.str().splitlines() - if 'Traceback (most recent call last)' in x] - assert len(traceback_lines) == 1 # make sure there are no duplicated tracebacks (#44) + assert "During handling of the above exception" not in result.stdout.str() + assert "Differing items:" not in result.stdout.str() + traceback_lines = [ + x + for x in result.stdout.str().splitlines() + if "Traceback (most recent call last)" in x + ] + assert ( + len(traceback_lines) == 1 + ) # make sure there are no duplicated tracebacks (#44) -@pytest.mark.skipif(sys.version_info[0] < 3, reason='Py3 only') +def test_monkeypatch_no_terminal(testdir): + """Don't crash without 'terminal' plugin. + """ + testdir.makepyfile( + """ + def test_foo(mocker): + stub = mocker.stub() + stub(1, greet='hello') + stub.assert_called_once_with(1, greet='hey') + """ + ) + result = runpytest_subprocess(testdir, "-p", "no:terminal", "-s") + assert result.ret == 1 + assert result.stdout.lines == [] + + +@pytest.mark.skipif(sys.version_info[0] < 3, reason="Py3 only") def test_standalone_mock(testdir): """Check that the "mock_use_standalone" is being used. """ - testdir.makepyfile(""" + testdir.makepyfile( + """ def test_foo(mocker): pass - """) - testdir.makeini(""" + """ + ) + testdir.makeini( + """ [pytest] mock_use_standalone_module = true - """) + """ + ) result = runpytest_subprocess(testdir) assert result.ret == 3 - result.stderr.fnmatch_lines([ - "*No module named 'mock'*", - ]) + result.stderr.fnmatch_lines(["*No module named 'mock'*"]) def runpytest_subprocess(testdir, *args): """Testdir.runpytest_subprocess only available in pytest-2.8+""" - if hasattr(testdir, 'runpytest_subprocess'): + if hasattr(testdir, "runpytest_subprocess"): return testdir.runpytest_subprocess(*args) else: # pytest 2.7.X return testdir.runpytest(*args) -@pytest.mark.usefixtures('needs_assert_rewrite') +@pytest.mark.usefixtures("needs_assert_rewrite") def test_detailed_introspection(testdir): """Check that the "mock_use_standalone" is being used. """ - testdir.makepyfile(""" + testdir.makepyfile( + """ def test(mocker): m = mocker.Mock() m('fo') m.assert_called_once_with('', bar=4) - """) - result = testdir.runpytest('-s') - result.stdout.fnmatch_lines([ - "*AssertionError: Expected call: mock('', bar=4)*", - "*Actual call: mock('fo')*", + """ + ) + result = testdir.runpytest("-s") + if PY38: + expected_lines = [ + "*AssertionError: expected call not found.", + "*Expected: mock('', bar=4)", + "*Actual: mock('fo')", + ] + else: + expected_lines = [ + "*AssertionError: Expected call: mock('', bar=4)*", + "*Actual call: mock('fo')*", + ] + expected_lines += [ "*pytest introspection follows:*", - '*Args:', + "*Args:", "*assert ('fo',) == ('',)", "*At index 0 diff: 'fo' != ''*", "*Use -v to get the full diff*", @@ -549,14 +642,35 @@ "*Right contains more items:*", "*{'bar': 4}*", "*Use -v to get the full diff*", - ]) + ] + result.stdout.fnmatch_lines(expected_lines) def test_assert_called_with_unicode_arguments(mocker): """Test bug in assert_call_with called with non-ascii unicode string (#91)""" stub = mocker.stub() - stub(b'l\xc3\xb6k'.decode('UTF-8')) + stub(b"l\xc3\xb6k".decode("UTF-8")) with pytest.raises(AssertionError): - stub.assert_called_with(u'lak') + stub.assert_called_with(u"lak") + +def test_plain_stopall(testdir): + """patch.stopall() in a test should not cause an error during unconfigure (#137)""" + testdir.makepyfile( + """ + import random + + def get_random_number(): + return random.randint(0, 100) + + def test_get_random_number(mocker): + patcher = mocker.mock_module.patch("random.randint", lambda x, y: 5) + patcher.start() + assert get_random_number() == 5 + mocker.mock_module.patch.stopall() + """ + ) + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines("* 1 passed in *") + assert "RuntimeError" not in result.stderr.str() diff -Nru pytest-mock-1.7.1/tox.ini pytest-mock-1.10.4/tox.ini --- pytest-mock-1.7.1/tox.ini 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/tox.ini 2019-04-17 17:23:43.000000000 +0000 @@ -1,15 +1,10 @@ [tox] -envlist = py{27,34,35,36}-pytest{30,31,32,33,34},linting,norewrite +envlist = py{27,34,35,36,37}, linting, norewrite [testenv] passenv = USER USERNAME deps = coverage - pytest30: pytest~=3.0 - pytest31: pytest~=3.1 - pytest32: pytest~=3.2 - pytest33: pytest~=3.3 - pytest34: pytest~=3.4 commands = coverage run --append --source=pytest_mock.py -m pytest test_pytest_mock.py @@ -18,11 +13,14 @@ pytest test_pytest_mock.py --assert=plain -ra [testenv:linting] -skip_install=True -deps = - pytest-flakes - restructuredtext_lint - pygments -commands = - py.test --flakes pytest_mock.py test_pytest_mock.py -m flakes - rst-lint CHANGELOG.rst README.rst +skipsdist = True +usedevelop = True +extras = dev +basepython = python3.6 +commands = pre-commit run --all-files --show-diff-on-failure + +[pytest] +addopts = -ra + +[flake8] +max-line-length = 88 diff -Nru pytest-mock-1.7.1/.travis.yml pytest-mock-1.10.4/.travis.yml --- pytest-mock-1.7.1/.travis.yml 2018-03-01 10:53:08.000000000 +0000 +++ pytest-mock-1.10.4/.travis.yml 2019-04-17 17:23:43.000000000 +0000 @@ -1,12 +1,9 @@ language: python -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" +dist: xenial install: - - pip install tox-travis coveralls + - pip install -U pip + - pip install tox coveralls script: - tox @@ -14,8 +11,25 @@ after_success: - coveralls +stages: +- test +- name: deploy + if: repo = pytest-dev/pytest-mock AND tag IS present + jobs: include: + - python: '2.7' + env: TOXENV=py27 + - python: '3.4' + env: TOXENV=py34 + - python: '3.5' + env: TOXENV=py35 + - python: '3.6' + env: TOXENV=py36 + - python: '3.7' + env: TOXENV=py37 + - python: '3.8-dev' + env: TOXENV=py38 - python: '3.6' env: TOXENV=linting - python: '3.6'