summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.carthorse.yml9
-rw-r--r--.circleci/config.yml118
-rw-r--r--.coveragerc14
-rw-r--r--.gitignore7
-rw-r--r--.readthedocs.yml8
-rw-r--r--.testr.conf4
-rw-r--r--.travis.yml26
-rw-r--r--CHANGELOG.rst206
-rw-r--r--MANIFEST.in2
-rw-r--r--NEWS79
-rw-r--r--README.rst19
-rw-r--r--TEST_MAPPING8
-rw-r--r--backport.py147
l---------[-rw-r--r--]docs/changelog.txt5
-rw-r--r--docs/conf.py6
-rw-r--r--docs/index.txt225
-rw-r--r--extendmock.py1
-rw-r--r--lastsync.txt1
-rw-r--r--mock.wpr26
-rw-r--r--mock/mock.py483
-rw-r--r--mock/tests/conftest.py6
-rw-r--r--mock/tests/support.py36
-rw-r--r--mock/tests/testcallable.py10
-rw-r--r--mock/tests/testhelpers.py352
-rw-r--r--mock/tests/testhelpers_py3.py23
-rw-r--r--mock/tests/testmagicmethods.py38
-rw-r--r--mock/tests/testmock.py546
-rw-r--r--mock/tests/testpatch.py243
-rw-r--r--mock/tests/testsealable.py176
-rw-r--r--mock/tests/testsentinel.py15
-rw-r--r--mock/tests/testsupport.py14
-rw-r--r--mock/tests/testwith.py47
-rw-r--r--release.py92
-rw-r--r--requirements.txt6
-rw-r--r--setup.cfg34
-rwxr-xr-xsetup.py10
-rwxr-xr-xtools/applypatch-transform38
-rwxr-xr-xtools/pre-applypatch36
-rw-r--r--tox.ini22
-rw-r--r--unittest.cfg95
40 files changed, 977 insertions, 2256 deletions
diff --git a/.carthorse.yml b/.carthorse.yml
deleted file mode 100644
index d8f3a9a..0000000
--- a/.carthorse.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-carthorse:
- version-from: setup.py
- tag-format: "{version}"
- when:
- - version-not-tagged
- actions:
- - run: "sudo pip install -e .[build]"
- - run: "twine upload -u carthorse-mock -p $PYPI_PASS dist/*"
- - create-tag
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 8416914..0000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,118 +0,0 @@
-version: 2.1
-
-orbs:
- python: cjw296/python-ci@2
-
-jobs:
- check-package:
- parameters:
- image:
- type: string
- python:
- type: string
- default: "python"
- docker:
- - image: << parameters.image >>
- steps:
- - python/check-package:
- package: "mock"
- test:
- - run:
- name: "Import package"
- command: << parameters.python >> -c "import mock"
-
-
-common: &common
- jobs:
- - python/pip-run-tests:
- name: python27
- image: circleci/python:2.7
- - python/pip-run-tests:
- name: python34
- image: circleci/python:3.4
- - python/pip-run-tests:
- name: python35
- image: circleci/python:3.5
- - python/pip-run-tests:
- name: python36
- image: circleci/python:3.6
- - python/pip-run-tests:
- name: python37
- image: circleci/python:3.7
- - python/pip-run-tests:
- name: pypy27
- image: pypy:2.7
- - python/pip-run-tests:
- name: pypy36
- image: pypy:3.6
-
- - python/coverage:
- name: coverage
- requires:
- - python27
- - python34
- - python35
- - python36
- - python37
- - pypy27
- - pypy36
-
- - python/pip-docs:
- name: docs
- requires:
- - coverage
-
- - python/pip-setuptools-build-package:
- name: package
- requires:
- - docs
- filters:
- branches:
- only: master
-
- - check-package:
- name: check-package-python27
- image: circleci/python:2.7
- requires:
- - package
-
- - check-package:
- name: check-package-python37
- image: circleci/python:3.7
- requires:
- - package
-
- - check-package:
- name: check-package-pypy27
- image: pypy:2.7
- python: pypy
- requires:
- - package
-
- - check-package:
- name: check-package-pypy36
- image: pypy:3.6
- python: pypy3
- requires:
- - package
-
- - python/release:
- name: release
- config: .carthorse.yml
- requires:
- - check-package-python27
- - check-package-python37
- - check-package-pypy27
- - check-package-pypy36
-
-workflows:
- push:
- <<: *common
- periodic:
- <<: *common
- triggers:
- - schedule:
- cron: "0 1 * * *"
- filters:
- branches:
- only: master
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 5a29219..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,14 +0,0 @@
-[run]
-source = mock
-omit = mock/tests/__main__.py
-
-[report]
-exclude_lines =
- pragma: no cover
- if __name__ == .__main__.:
- : pass
-
-[paths]
-source =
- mock/
- /root/project/mock/
diff --git a/.gitignore b/.gitignore
index b488ed9..93d1155 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.*\.pyc
+*.rej
html/
mock\.egg-info/
mock\.wpu
@@ -12,6 +13,8 @@ runtox
*.pyc
.testrepository
.*.swp
+AUTHORS
+ChangeLog
+.eggs
+README.saved
README.html
-.coverage
-.coverage.*
diff --git a/.readthedocs.yml b/.readthedocs.yml
deleted file mode 100644
index 7687b8a..0000000
--- a/.readthedocs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-version: 2
-python:
- version: 3.7
- install:
- - method: pip
- path: .
- extra_requirements:
- - docs
diff --git a/.testr.conf b/.testr.conf
new file mode 100644
index 0000000..8a65628
--- /dev/null
+++ b/.testr.conf
@@ -0,0 +1,4 @@
+[DEFAULT]
+test_command=${PYTHON:-python} -m subunit.run discover . $LISTOPT $IDOPTION
+test_id_option=--load-list $IDFILE
+test_list_option=--list
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a13b528
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,26 @@
+sudo: false
+language: python
+python:
+ - "2.7"
+ - "3.3"
+ - "3.4"
+ - "3.5"
+ - "3.6"
+ - pypy
+ - pypy3
+matrix:
+ include:
+# Travis nightly look to be 3.5.0a4, b3 is out and the syntax error we see
+# doesn't happen in trunk.
+ - python: "nightly"
+ env: SKIP_DOCS=1
+install:
+ - pip install -U pip
+ - pip install -U wheel setuptools
+ - pip install -U .[docs,test]
+ - pip list
+ - python --version
+script:
+ - unit2
+ - if [ -z "$SKIP_DOCS" ]; then python setup.py build_sphinx; fi
+ - rst2html.py --strict README.rst README.html
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
deleted file mode 100644
index 919648b..0000000
--- a/CHANGELOG.rst
+++ /dev/null
@@ -1,206 +0,0 @@
-3.0.5
------
-
-- Issue #31855: :func:`unittest.mock.mock_open` results now respects the
- argument of read([size]). Patch contributed by Rémi Lapeyre.
-
-3.0.4
------
-
-- Include the license, readme and changelog in the source distribution.
-
-3.0.3
------
-
-- Fixed patching of dictionaries, when specifying the target with a
- unicode on Python 2.
-
-3.0.2
------
-
-- Add missing ``funcsigs`` dependency on Python 2.
-
-3.0.1
------
-
-- Fix packaging issue where ``six`` was missed as a dependency.
-
-3.0.0
------
-
-- Issue #35226: Recursively check arguments when testing for equality of
- :class:`unittest.mock.call` objects and add note that tracking of
- parameters used to create ancestors of mocks in ``mock_calls`` is not
- possible.
-
-- Issue #31177: Fix bug that prevented using :meth:`reset_mock
- <unittest.mock.Mock.reset_mock>` on mock instances with deleted attributes
-
-- Issue #26704: Added test demonstrating double-patching of an instance
- method. Patch by Anthony Sottile.
-
-- Issue #35500: Write expected and actual call parameters on separate lines
- in :meth:`unittest.mock.Mock.assert_called_with` assertion errors.
- Contributed by Susan Su.
-
-- Issue #35330: When a :class:`Mock` instance was used to wrap an object, if
- `side_effect` is used in one of the mocks of it methods, don't call the
- original implementation and return the result of using the side effect the
- same way that it is done with return_value.
-
-- Issue #30541: Add new function to seal a mock and prevent the
- automatically creation of child mocks. Patch by Mario Corchero.
-
-- Issue #35022: :class:`unittest.mock.MagicMock` now supports the
- ``__fspath__`` method (from :class:`os.PathLike`).
-
-- Issue #33516: :class:`unittest.mock.MagicMock` now supports the
- ``__round__`` magic method.
-
-- Issue #35512: :func:`unittest.mock.patch.dict` used as a decorator with
- string target resolves the target during function call instead of during
- decorator construction. Patch by Karthikeyan Singaravelan.
-
-- Issue #36366: Calling ``stop()`` on an unstarted or stopped
- :func:`unittest.mock.patch` object will now return `None` instead of
- raising :exc:`RuntimeError`, making the method idempotent. Patch
- byKarthikeyan Singaravelan.
-
-- Issue #35357: Internal attributes' names of unittest.mock._Call and
- unittest.mock.MagicProxy (name, parent & from_kall) are now prefixed with
- _mock_ in order to prevent clashes with widely used object attributes.
- Fixed minor typo in test function name.
-
-- Issue #20239: Allow repeated assignment deletion of
- :class:`unittest.mock.Mock` attributes. Patch by Pablo Galindo.
-
-- Issue #35082: Don't return deleted attributes when calling dir on a
- :class:`unittest.mock.Mock`.
-
-- Issue #0: Improved an error message when mock assert_has_calls fails.
-
-- Issue #23078: Add support for :func:`classmethod` and :func:`staticmethod`
- to :func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa.
-
-- Issue #21478: Calls to a child function created with
- :func:`unittest.mock.create_autospec` should propagate to the parent.
- Patch by Karthikeyan Singaravelan.
-
-- Issue #36598: Fix ``isinstance`` check for Mock objects with spec when the
- code is executed under tracing. Patch by Karthikeyan Singaravelan.
-
-- Issue #32933: :func:`unittest.mock.mock_open` now supports iteration over
- the file contents. Patch by Tony Flury.
-
-- Issue #21269: Add ``args`` and ``kwargs`` properties to mock call objects.
- Contributed by Kumar Akshay.
-
-- Issue #17185: Set ``__signature__`` on mock for :mod:`inspect` to get
- signature. Patch by Karthikeyan Singaravelan.
-
-- Issue #35047: ``unittest.mock`` now includes mock calls in exception
- messages if ``assert_not_called``, ``assert_called_once``, or
- ``assert_called_once_with`` fails. Patch by Petter Strandmark.
-
-- Issue #28380: unittest.mock Mock autospec functions now properly support
- assert_called, assert_not_called, and assert_called_once.
-
-- Issue #28735: Fixed the comparison of mock.MagickMock with mock.ANY.
-
-- Issue #20804: The unittest.mock.sentinel attributes now preserve their
- identity when they are copied or pickled.
-
-- Issue #28961: Fix unittest.mock._Call helper: don't ignore the name parameter
- anymore. Patch written by Jiajun Huang.
-
-- Issue #26750: unittest.mock.create_autospec() now works properly for
- subclasses of property() and other data descriptors.
-
-- Issue #21271: New keyword only parameters in reset_mock call.
-
-- Issue #26807: mock_open 'files' no longer error on readline at end of file.
- Patch from Yolanda Robla.
-
-- Issue #25195: Fix a regression in mock.MagicMock. _Call is a subclass of
- tuple (changeset 3603bae63c13 only works for classes) so we need to
- implement __ne__ ourselves. Patch by Andrew Plummer.
-
-2.0.0 and earlier
------------------
-
-- Issue #26323: Add Mock.assert_called() and Mock.assert_called_once()
- methods to unittest.mock. Patch written by Amit Saha.
-
-- Issue #22138: Fix mock.patch behavior when patching descriptors. Restore
- original values after patching. Patch contributed by Sean McCully.
-
-- Issue #24857: Comparing call_args to a long sequence now correctly returns a
- boolean result instead of raising an exception. Patch by A Kaptur.
-
-- Issue #23004: mock_open() now reads binary data correctly when the type of
- read_data is bytes. Initial patch by Aaron Hill.
-
-- Issue #21750: mock_open.read_data can now be read from each instance, as it
- could in Python 3.3.
-
-- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely.
- Patch from Nicola Palumbo and Laurent De Buyst.
-
-- Issue #23661: unittest.mock side_effects can now be exceptions again. This
- was a regression vs Python 3.4. Patch from Ignacio Rossi
-
-- Issue #23310: Fix MagicMock's initializer to work with __methods__, just
- like configure_mock(). Patch by Kasia Jachim.
-
-- Issue #23568: Add rdivmod support to MagicMock() objects.
- Patch by Håkan Lövdahl.
-
-- Issue #23581: Add matmul support to MagicMock. Patch by Håkan Lövdahl.
-
-- Issue #23326: Removed __ne__ implementations. Since fixing default __ne__
- implementation in issue #21408 they are redundant. *** NOT BACKPORTED ***
-
-- Issue #21270: We now override tuple methods in mock.call objects so that
- they can be used as normal call attributes.
-
-- Issue #21256: Printout of keyword args should be in deterministic order in
- a mock function call. This will help to write better doctests.
-
-- Issue #21262: New method assert_not_called for Mock.
- It raises AssertionError if the mock has been called.
-
-- Issue #21238: New keyword argument `unsafe` to Mock. It raises
- `AttributeError` incase of an attribute startswith assert or assret.
-
-- Issue #21239: patch.stopall() didn't work deterministically when the same
- name was patched more than once.
-
-- Issue #21222: Passing name keyword argument to mock.create_autospec now
- works.
-
-- Issue #17826: setting an iterable side_effect on a mock function created by
- create_autospec now works. Patch by Kushal Das.
-
-- Issue #17826: setting an iterable side_effect on a mock function created by
- create_autospec now works. Patch by Kushal Das.
-
-- Issue #20968: unittest.mock.MagicMock now supports division.
- Patch by Johannes Baiter.
-
-- Issue #20189: unittest.mock now no longer assumes that any object for
- which it could get an inspect.Signature is a callable written in Python.
- Fix courtesy of Michael Foord.
-
-- Issue #17467: add readline and readlines support to mock_open in
- unittest.mock.
-
-- Issue #17015: When it has a spec, a Mock object now inspects its signature
- when matching calls, so that arguments can be matched positionally or
- by name.
-
-- Issue #15323: improve failure message of Mock.assert_called_once_with
-
-- Issue #14857: fix regression in references to PEP 3135 implicit __class__
- closure variable (Reopens issue #12370)
-
-- Issue #14295: Add unittest.mock
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 7f47ab6..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include LICENSE.txt
-include *.rst
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..2120418
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,79 @@
+Library
+-------
+
+- Issue #26323: Add Mock.assert_called() and Mock.assert_called_once()
+ methods to unittest.mock. Patch written by Amit Saha.
+
+- Issue #22138: Fix mock.patch behavior when patching descriptors. Restore
+ original values after patching. Patch contributed by Sean McCully.
+
+- Issue #24857: Comparing call_args to a long sequence now correctly returns a
+ boolean result instead of raising an exception. Patch by A Kaptur.
+
+- Issue #23004: mock_open() now reads binary data correctly when the type of
+ read_data is bytes. Initial patch by Aaron Hill.
+
+- Issue #21750: mock_open.read_data can now be read from each instance, as it
+ could in Python 3.3.
+
+- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely.
+ Patch from Nicola Palumbo and Laurent De Buyst.
+
+- Issue #23661: unittest.mock side_effects can now be exceptions again. This
+ was a regression vs Python 3.4. Patch from Ignacio Rossi
+
+- Issue #23310: Fix MagicMock's initializer to work with __methods__, just
+ like configure_mock(). Patch by Kasia Jachim.
+
+- Issue #23568: Add rdivmod support to MagicMock() objects.
+ Patch by Håkan Lövdahl.
+
+- Issue #23581: Add matmul support to MagicMock. Patch by Håkan Lövdahl.
+
+- Issue #23326: Removed __ne__ implementations. Since fixing default __ne__
+ implementation in issue #21408 they are redundant. *** NOT BACKPORTED ***
+
+- Issue #21270: We now override tuple methods in mock.call objects so that
+ they can be used as normal call attributes.
+
+- Issue #21256: Printout of keyword args should be in deterministic order in
+ a mock function call. This will help to write better doctests.
+
+- Issue #21262: New method assert_not_called for Mock.
+ It raises AssertionError if the mock has been called.
+
+- Issue #21238: New keyword argument `unsafe` to Mock. It raises
+ `AttributeError` incase of an attribute startswith assert or assret.
+
+- Issue #21239: patch.stopall() didn't work deterministically when the same
+ name was patched more than once.
+
+- Issue #21222: Passing name keyword argument to mock.create_autospec now
+ works.
+
+- Issue #17826: setting an iterable side_effect on a mock function created by
+ create_autospec now works. Patch by Kushal Das.
+
+- Issue #17826: setting an iterable side_effect on a mock function created by
+ create_autospec now works. Patch by Kushal Das.
+
+- Issue #20968: unittest.mock.MagicMock now supports division.
+ Patch by Johannes Baiter.
+
+- Issue #20189: unittest.mock now no longer assumes that any object for
+ which it could get an inspect.Signature is a callable written in Python.
+ Fix courtesy of Michael Foord.
+
+- Issue #17467: add readline and readlines support to mock_open in
+ unittest.mock.
+
+- Issue #17015: When it has a spec, a Mock object now inspects its signature
+ when matching calls, so that arguments can be matched positionally or
+ by name.
+
+- Issue #15323: improve failure message of Mock.assert_called_once_with
+
+- Issue #14857: fix regression in references to PEP 3135 implicit __class__
+ closure variable (Reopens issue #12370)
+
+- Issue #14295: Add unittest.mock
diff --git a/README.rst b/README.rst
index b4f3163..2ba1b38 100644
--- a/README.rst
+++ b/README.rst
@@ -7,7 +7,7 @@ mock is now part of the Python standard library, available as `unittest.mock
onwards.
This package contains a rolling backport of the standard library mock code
-compatible with Python 2.7 and 3.4 and up.
+compatible with Python 2.7 and 3.3 and up.
Please see the standard library documentation for more details.
@@ -17,20 +17,13 @@ Please see the standard library documentation for more details.
:License: `BSD License`_
:Support: `Mailing list (testing-in-python@lists.idyll.org)
<http://lists.idyll.org/listinfo/testing-in-python>`_
-:Code: `GitHub
- <https://github.com/testing-cabal/mock>`_
:Issue tracker: `GitHub Issues
<https://github.com/testing-cabal/mock/issues>`_
:Build status:
- |CircleCI|_ |Docs|_
+ .. image:: https://travis-ci.org/testing-cabal/mock.svg?branch=master
+ :target: https://travis-ci.org/testing-cabal/mock
- .. |CircleCI| image:: https://circleci.com/gh/testing-cabal/mock/tree/master.svg?style=shield
- .. _CircleCI: https://circleci.com/gh/testing-cabal/mock/tree/master
-
- .. |Docs| image:: https://readthedocs.org/projects/mock/badge/?version=latest
- .. _Docs: http://mock.readthedocs.org/en/latest/
-
-.. _Mock Homepage: http://mock.readthedocs.org/en/latest/
-.. _BSD License: https://github.com/testing-cabal/mock/blob/master/LICENSE.txt
+.. _Mock Homepage: https://github.com/testing-cabal/mock
+.. _BSD License: http://github.com/testing-cabal/mock/blob/master/LICENSE.txt
.. _Python Docs: https://docs.python.org/dev/library/unittest.mock.html
-.. _mock on PyPI: https://pypi.org/project/mock/
+.. _mock on PyPI: http://pypi.python.org/pypi/mock
diff --git a/TEST_MAPPING b/TEST_MAPPING
deleted file mode 100644
index 61a80b2..0000000
--- a/TEST_MAPPING
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "presubmit" : [
- {
- "name" : "acloud_test",
- "host" : true
- }
- ]
-}
diff --git a/backport.py b/backport.py
deleted file mode 100644
index b2ab523..0000000
--- a/backport.py
+++ /dev/null
@@ -1,147 +0,0 @@
-import re
-from argparse import ArgumentParser
-from os.path import dirname, abspath, join
-from subprocess import check_output, call
-
-
-def git(command, repo):
- return check_output('git '+command, cwd=repo, shell=True).decode()
-
-
-def repo_state_bad(mock_repo):
- status = git('status', mock_repo)
- if 'You are in the middle of an am session' in status:
- print(f'Mock repo at {mock_repo} needs cleanup:\n')
- call('git status', shell=True)
- return True
-
-
-def cleanup_old_patches(mock_repo):
- print('cleaning up old patches:')
- call('rm -vf /tmp/*.mock.patch', shell=True)
- call('find . -name "*.rej" -print -delete', shell=True, cwd=mock_repo)
-
-
-def find_initial_cpython_rev():
- with open('lastsync.txt') as source:
- return source.read().strip()
-
-
-def cpython_revs_affecting_mock(cpython_repo, start):
- revs = git(f'log --no-merges --format=%H {start}.. '
- f'-- Lib/unittest/mock.py Lib/unittest/test/testmock/',
- repo=cpython_repo).split()
- revs.reverse()
- print(f'{len(revs)} patches that may need backporting')
- return revs
-
-
-def has_been_backported(mock_repo, cpython_rev):
- backport_rev = git(f'log --format=%H --grep "Backports: {cpython_rev}"',
- repo=mock_repo).strip()
- if backport_rev:
- print(f'{cpython_rev} backported in {backport_rev}')
- return True
- print(f'{cpython_rev} has not been backported')
-
-
-def extract_patch_for(cpython_repo, rev):
- return git(f'format-patch -1 --no-stat --keep-subject --signoff --stdout {rev}',
- repo=cpython_repo)
-
-
-def munge(rev, patch):
-
- sign_off = 'Signed-off-by:'
- patch = patch.replace(sign_off, f'Backports: {rev}\n{sign_off}', 1)
-
- for pattern, sub in (
- ('(a|b)/Lib/unittest/mock.py', r'\1/mock/mock.py'),
- (r'(a|b)/Lib/unittest/test/testmock/(\S+)', r'\1/mock/tests/\2'),
- ('(a|b)/Misc/NEWS', r'\1/NEWS'),
- ('(a|b)/NEWS.d/next/[^/]+/(.+\.rst)', r'\1/NEWS.d/\2'),
- ):
- patch = re.sub(pattern, sub, patch)
- return patch
-
-
-def apply_patch(mock_repo, rev, patch):
- patch_path = f'/tmp/{rev}.mock.patch'
-
- with open(patch_path, 'w') as target:
- target.write(patch)
- print(f'wrote {patch_path}')
-
- call(f'git am -k '
- f'--include "mock/*" --include NEWS --include "NEWS.d/*" '
- f'--reject {patch_path} ',
- cwd=mock_repo, shell=True)
-
-
-def update_last_sync(mock_repo, rev):
- with open(join(mock_repo, 'lastsync.txt'), 'w') as target:
- target.write(rev+'\n')
- print(f'update lastsync.txt to {rev}')
-
-
-def rev_from_mock_patch(text):
- match = re.search('Backports: ([a-z0-9]+)', text)
- return match.group(1)
-
-
-def skip_current(mock_repo, reason):
- text = git('am --show-current-patch', repo=mock_repo)
- rev = rev_from_mock_patch(text)
- git('am --abort', repo=mock_repo)
- print(f'skipping {rev}')
- update_last_sync(mock_repo, rev)
- call(f'git commit -m "Backports: {rev}, skipped: {reason}" lastsync.txt', shell=True, cwd=mock_repo)
- cleanup_old_patches(mock_repo)
-
-
-def commit_last_sync(revs, mock_repo):
- print('Yay! All caught up!')
- if len(revs):
- git('commit -m "latest sync point" lastsync.txt', repo=mock_repo)
-
-
-def main():
- args = parse_args()
-
- if args.skip_current:
- return skip_current(args.mock, args.skip_reason)
-
- if repo_state_bad(args.mock):
- return
-
- cleanup_old_patches(args.mock)
-
- initial_cpython_rev = find_initial_cpython_rev()
-
- revs = cpython_revs_affecting_mock(args.cpython, initial_cpython_rev)
- for rev in revs:
-
- if has_been_backported(args.mock, rev):
- update_last_sync(args.mock, rev)
- continue
-
- patch = extract_patch_for(args.cpython, rev)
- patch = munge(rev, patch)
- apply_patch(args.mock, rev, patch)
- break
-
- else:
- commit_last_sync(revs, args.mock)
-
-
-def parse_args():
- parser = ArgumentParser()
- parser.add_argument('--cpython', default='../cpython')
- parser.add_argument('--mock', default=abspath(dirname(__file__)))
- parser.add_argument('--skip-current', action='store_true')
- parser.add_argument('--skip-reason', default='it has no changes needed here.')
- return parser.parse_args()
-
-
-if __name__ == '__main__':
- main()
diff --git a/docs/changelog.txt b/docs/changelog.txt
index 4de03af..22ec9b8 100644..120000
--- a/docs/changelog.txt
+++ b/docs/changelog.txt
@@ -1,4 +1 @@
-Changelog
-=========
-
-.. include:: ../CHANGELOG.rst
+../ChangeLog \ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index d2be5a5..d32357d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -33,6 +33,7 @@ import os
import sys
import mock
from mock import * # yeah, I know :-/
+import unittest2
import __main__
if os.getcwd() not in sys.path:
@@ -71,7 +72,10 @@ copyright = u'2007-2015, Michael Foord & the mock team'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents. Supplied by pbr.
#
-version = release = mock.mock.__version__
+# The short X.Y version.
+version = mock.mock._v.brief_string()
+# The full version, including alpha/beta/rc tags.
+release = mock.__version__
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used: (Set from pbr)
diff --git a/docs/index.txt b/docs/index.txt
index 4e8bc17..6c8e37b 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -1,29 +1,58 @@
-===================================
+====================================
Mock - Mocking and Testing Library
-===================================
-
-.. include:: ../README.rst
+====================================
+
+:Version: |release|
+:Date: |today|
+:Homepage: `Mock Homepage`_
+:Download: `Mock on PyPI`_
+:Documentation: `Python Docs`_
+:License: `BSD License`_
+:Support: `Mailing list (testing-in-python@lists.idyll.org)
+ <http://lists.idyll.org/listinfo/testing-in-python>`_
+:Issue tracker: `GitHub Issues
+ <https://github.com/testing-cabal/mock/issues>`_
+:Last sync: cb6aab1248c4aec4dd578bea717854505a6fb55d
+
+.. _Mock Homepage: https://github.com/testing-cabal/mock
+.. _BSD License: http://github.com/testing-cabal/mock/blob/master/LICENSE.txt
+.. _Python Docs: https://docs.python.org/dev/library/unittest.mock.html
.. module:: mock
:synopsis: Mock object and testing library.
.. index:: introduction
+TOC
++++
+
.. toctree::
- :hidden:
+ :maxdepth: 2
changelog
-Python Version Compatibility
-++++++++++++++++++++++++++++
+Introduction
+++++++++++++
+
+mock is a library for testing in Python. It allows you to replace parts of
+your system under test with mock objects and make assertions about how they
+have been used.
-* Version 1.0.1 is the last version compatible with Python < 2.6.
+mock is now part of the Python standard library, available as
+``unittest.mock`` in Python 3.3 onwards. However, if you are writing code that
+runs on multiple versions of Python the ``mock`` package is better, as you get
+the newest features from the latest release of Python available for all
+Pythons.
-* Version 1.3.0 is the last version compatible with Python 3.2.
+The ``mock`` package contains a rolling backport of the standard library mock
+code compatible with Python 2.7 and 3.3 and up.
-* Version 2.0.0 is the last version compatible with Python 2.6.
+* Python 2.6 is supported by mock 2.0.0 and below.
-* Version 2.0.0 is the last version offering official Jython support.
+* Python 3.2 is supported by mock 1.3.0 and below - with pip no longer
+supporting 3.2, we cannot test against that version anymore.
+
+Please see the standard library documentation for usage details.
.. index:: installing
.. _installing:
@@ -31,13 +60,17 @@ Python Version Compatibility
Installing
++++++++++
+The current version is |release|. Mock is stable and widely used.
+
+* `mock on PyPI <http://pypi.python.org/pypi/mock>`_
+
.. index:: repository
.. index:: git
You can checkout the latest development version from GitHub
repository with the following command:
- ``git clone https://github.com/testing-cabal/mock.git``
+ ``git clone https://github.com/testing-cabal/mock``
.. index:: pip
@@ -46,11 +79,18 @@ You can install mock with pip:
| ``pip install -U mock``
+Alternatively you can download the mock distribution from PyPI and after
+unpacking run:
+
+ ``python setup.py install``
+
+
.. index:: bug reports
Bug Reports
+++++++++++
+Mock uses `unittest2 <http://pypi.python.org/pypi/unittest2>`_ for its own
Issues with the backport process, such as compatibility with a particular
Python, should be reported to the `bug tracker
<https://github.com/testing-cabal/mock/issues>`_. Feature requests and issues
@@ -59,10 +99,21 @@ with Mock functionality should be reported to the `Python bug tracker
.. index:: python changes
-Changelog
-+++++++++
+Python Changes
+++++++++++++++
+
+Python NEWS entries from cPython:
+
+.. include:: ../NEWS
-See the :doc:`change log <changelog>`.
+.. index:: older versions
+
+Older Versions of Python
+++++++++++++++++++++++++
+
+Version 1.0.1 is the last version compatible with Python < 2.6.
+
+Version 2.0.0 is the last version compatible with Python 2.6.
.. index:: maintainer notes
@@ -70,112 +121,74 @@ Maintainer Notes
++++++++++++++++
Development
------------
+===========
Checkout from git (see :ref:`installing`) and submit pull requests.
Committers can just push as desired: since all semantic development takes
place in cPython, the backport process is as lightweight as we can make it.
-mock is CI tested using Travis-CI on Python versions 2.7, 3.4,
-3.5, 3.6, pypy, pypy3.
-
-If you end up fixing anything backport-specific, please add an entry
-to the top of ``CHANGELOG.rst`` so it shows up in the next release
-notes.
+mock is CI tested using Travis-CI on Python versions 2.7, 3.3, 3.4,
+3.5, nightly Python 3 builds, pypy, pypy3. Jython support is desired, if
+someone could contribute a patch to .travis.yml to support it that would be
+excellent.
Releasing
----------
+=========
NB: please use semver. Bump the major component on API breaks, minor on all
non-bugfix changes, patch on bugfix only changes.
-1. Run ``release.py [major|minor|bugfix]`` which will roll out new
- NEWS items, bump the version number and create a commit for the release.
-
-2. Review that commit, feel free to amend it if you want to note anything
- manually in ``CHANGELOG.rst``.
+1. tag -s, push --tags origin master
+2. setup.py sdist bdist_wheel upload -s
-3. Push to the ``master`` branch on
- https://github.com/testing-cabal/mock.git and the Circle CI
- automation will take care of pushing releases to PyPI and
- creating a tag.
Backporting rules
------------------
-
-- ``isinstance`` checks in cPython to ``type`` need to check ``ClassTypes``.
- Code calling ``obj.isidentifier`` needs to change to ``_isidentifier(obj)``.
-
-- f-strings need to be rewritten using some other string substitution.
-
-- ``assertRaisesRegex`` needs to be ``assertRaisesRegexp`` for Python 2.
-
-- If test code won't compile on a particular version of Python, move it to
- a matching ``_py{version}.py`` file. If ``{version}`` isn't 3, adjust
- ``conftest.py``.
-
-- If code such as this causes coverage checking to drop below 100%:
+=================
- .. code-block:: python
-
- def will_never_be_called():
- pass
-
- It should be adjusted to the following pattern, preferably upstream,
- so that the ``.coveragerc`` in this repo knows to ignore it:
-
- .. code-block:: python
-
- def will_never_be_called(): pass
+isinstance checks in cPython to ``type`` need to check ``ClassTypes``.
+Code calling ``obj.isidentifier`` needs to change to ``_isidentifier(obj)``.
Backporting process
--------------------
-
-1. Clone cpython and mock into the same directory, eg:
-
- .. code-block:: bash
-
- mkdir vcs
- cd vcs
- git clone https://github.com/python/cpython.git
- git clone https://github.com/testing-cabal/mock.git
-
- Make sure they both on master and up to date!
-
-2. Create a branch in your ``mock`` clone and switch to it.
-
-3. Make sure you build a suitable virtualenv for Mock development
- and activate it. For backporting, this should use Python 3.7+.
-
-4. Run ``backport.py``:
-
- .. code-block:: bash
-
- cd vcs/mock
- python backport.py
-
- This will find the next cpython patch that needs to be applied, munge it
- and attempt to apply it with ``git am``.
-
- If it succeeds, run the tests and/or push your branch up to a fork and
- do a pull request into the master branch of the main repo to kick off
- the continuous integration tests.
-
- If it fails, you'll have to manually work with what ``git status`` shows
- to get the patch committed.
-
- If it turns out that there's nothing that should be applied from the failed commit,
- run ``python backport.py --skip-current``, maybe with ``--skip-reason``.
-
- If you have to make changes, please do a ``git commit --amend`` and add notes
- about what needed doing below the ``Signed-off-by`` block.
-
- If you have to make changes because tests fail with an applied patch, please
- make those changes in a followup commit and take note of the "Backporting rules"
- above.
-
-5. Rinse and repeat until ``backport.py`` reports no more patches need applying.
-
-6. If ``backport.py`` has updated ``lastsync.txt``, now would be a good time
- to commit that change.
+===================
+
+1. Patch your git am with `my patch <https://github.com/rbtcollins/git>`_.
+2. Install the applypatch-transform hook from tools/ to your .git hooks dir.
+3. Configure a pre-applypatch hook to test at least all the cPython versions
+ we support on each patch that is applied. I use containers, and a sample
+ script is in tools/pre-applypatch.
+4. Pull down the cPython git mirror: https://github.com/python/cpython.git
+5. Export the new revisions since the ``Last sync`` at the top of this
+ document::
+
+ revs=${lastsync}
+ rm migrate-export
+ git log --pretty="format:%H " $revs.. -- Lib/unittest/mock.py \
+ Lib/unittest/test/testmock/ > migrate-revs
+ tac migrate-revs > migrate-sorted-revs
+ for rev in $(< migrate-sorted-revs); do
+ git format-patch -1 $rev -k --stdout >> migrate-export;
+ done
+ echo NEW SYNC POINT: $(git rev-parse HEAD)
+
+6. Import into mock::
+
+ git am -k --reject $path-to-cpython/migrate-export
+
+ This will transform the patches automatically. Currently it will error
+ on every NEWS change as I haven't gotten around to making those patches
+ automatic. Fixup any errors that occur. When the patch is ready, do a ``git
+ add -u`` to update the index and then ``git am --continue`` to move onto
+ the next patch. If the patch is inappropriate e.g. the patch removing
+ __ne__ which would break older pythons, then either do ``git reset --hard;
+ git am --skip`` to discard any partially applied changes and skip over it,
+ or, if it has a NEWS entry thats worth preserving, edit it down to just
+ that, with a note such as we have for the ``__ne__`` patch, and continue on
+ from there.
+
+ The goal is that every patch work at all times.
+
+7. After the import is complete, update this document with the new sync point.
+
+8. Push to a personal branch and propose a PR to the main repo. This will make
+ Travis-CI test it. If it works, push to the main repo.
diff --git a/extendmock.py b/extendmock.py
new file mode 100644
index 0000000..0550d9f
--- /dev/null
+++ b/extendmock.py
@@ -0,0 +1 @@
+# merged into mock.py in Mock 0.7
diff --git a/lastsync.txt b/lastsync.txt
deleted file mode 100644
index 1f18392..0000000
--- a/lastsync.txt
+++ /dev/null
@@ -1 +0,0 @@
-11a8832c98b3db78727312154dd1d3ba76d639ec
diff --git a/mock.wpr b/mock.wpr
new file mode 100644
index 0000000..e1ded97
--- /dev/null
+++ b/mock.wpr
@@ -0,0 +1,26 @@
+#!wing
+#!version=4.0
+##################################################################
+# Wing IDE project file #
+##################################################################
+[project attributes]
+proj.directory-list = [{'dirloc': loc('.'),
+ 'excludes': [u'latex',
+ u'.hg',
+ u'.tox',
+ u'dist',
+ u'htmlcov',
+ u'extendmock.py',
+ u'__pycache__',
+ u'html',
+ u'build',
+ u'mock.egg-info',
+ u'tests/__pycache__',
+ u'.hgignore',
+ u'.hgtags'],
+ 'filter': '*',
+ 'include_hidden': 0,
+ 'recursive': 1,
+ 'watch_for_changes': 1}]
+proj.file-type = 'shared'
+testing.auto-test-file-specs = ('test*.py',)
diff --git a/mock/mock.py b/mock/mock.py
index 2d39253..beedd69 100644
--- a/mock/mock.py
+++ b/mock/mock.py
@@ -2,6 +2,7 @@
# Test tools for mocking and patching.
# E-mail: fuzzyman AT voidspace DOT org DOT uk
#
+# mock 2.0.0
# http://www.voidspace.org.uk/python/mock/
#
# Copyright (c) 2007-2013, Michael Foord & the mock team
@@ -50,12 +51,10 @@ __all__ = (
'NonCallableMagicMock',
'mock_open',
'PropertyMock',
- 'seal',
)
from functools import partial
-import io
import inspect
import pprint
import sys
@@ -63,14 +62,21 @@ try:
import builtins
except ImportError:
import __builtin__ as builtins
-from types import ModuleType, MethodType
-from unittest.util import safe_repr
+from types import ModuleType
import six
from six import wraps
-
-__version__ = '3.0.5'
-version_info = tuple(int(p) for p in __version__.split('.'))
+# GOOGLE
+# We're going to avoid using pbr so we don't have to import it into AOSP just
+# for the version info, instead we'll hardcode it. This will be safe since mock
+# dev is essentially stable and hasn't been changed in months.
+# from pbr.version import VersionInfo
+
+# _v = VersionInfo('mock').semantic_version()
+# __version__ = _v.release_string()
+# version_info = _v.version_tuple()
+__version__ = '2.0.0'
+version_info = (2, 0, 0, 'final', 0)
import mock
@@ -105,7 +111,13 @@ if six.PY2:
del _next
-_builtins = {name for name in dir(builtins) if not name.startswith('_')}
+_builtins = set(name for name in dir(builtins) if not name.startswith('_'))
+
+BaseExceptions = (BaseException,)
+if 'java' in sys.platform:
+ # jython
+ import java
+ BaseExceptions = (BaseException, java.lang.Throwable)
try:
_isidentifier = str.isidentifier
@@ -119,6 +131,11 @@ except AttributeError:
return False
return regex.match(string)
+self = 'im_self'
+builtin = '__builtin__'
+if six.PY3:
+ self = '__self__'
+ builtin = 'builtins'
# NOTE: This FILTER_DIR is not used. The binding in mock.FILTER_DIR is.
FILTER_DIR = True
@@ -135,8 +152,8 @@ def _is_instance_mock(obj):
def _is_exception(obj):
return (
- isinstance(obj, BaseException) or
- isinstance(obj, ClassTypes) and issubclass(obj, BaseException)
+ isinstance(obj, BaseExceptions) or
+ isinstance(obj, ClassTypes) and issubclass(obj, BaseExceptions)
)
@@ -144,8 +161,6 @@ class _slotted(object):
__slots__ = ['a']
-# Do not use this tuple. It was never documented as a public API.
-# It will be removed. It has no obvious signs of users on github.
DescriptorTypes = (
type(_slotted.a),
property,
@@ -194,32 +209,37 @@ def _check_signature(func, mock, skipfirst, instance=False):
sig.bind(*args, **kwargs)
_copy_func_details(func, checksig)
type(mock)._mock_check_sig = checksig
- type(mock).__signature__ = sig
def _copy_func_details(func, funcopy):
+ funcopy.__name__ = func.__name__
+ funcopy.__doc__ = func.__doc__
+ try:
+ funcopy.__text_signature__ = func.__text_signature__
+ except AttributeError:
+ pass
# we explicitly don't copy func.__dict__ into this copy as it would
# expose original attributes that should be mocked
- for attribute in (
- '__name__', '__doc__', '__text_signature__',
- '__module__', '__defaults__', '__kwdefaults__',
- ):
- try:
- setattr(funcopy, attribute, getattr(func, attribute))
- except AttributeError:
- pass
+ try:
+ funcopy.__module__ = func.__module__
+ except AttributeError:
+ pass
+ try:
+ funcopy.__defaults__ = func.__defaults__
+ except AttributeError:
+ pass
+ try:
+ funcopy.__kwdefaults__ = func.__kwdefaults__
+ except AttributeError:
+ pass
if six.PY2:
- try:
- funcopy.func_defaults = func.func_defaults
- except AttributeError:
- pass
+ funcopy.func_defaults = func.func_defaults
+ return
def _callable(obj):
if isinstance(obj, ClassTypes):
return True
- if isinstance(obj, (staticmethod, classmethod, MethodType)):
- return _callable(obj.__func__)
if getattr(obj, '__call__', None) is not None:
return True
return False
@@ -260,11 +280,13 @@ def _set_signature(mock, original, instance=False):
# creates a function with signature (*args, **kwargs) that delegates to a
# mock. It still does signature checking by calling a lambda with the same
# signature as the original.
+ if not _callable(original):
+ return
skipfirst = isinstance(original, ClassTypes)
result = _get_signature_object(original, instance, skipfirst)
if result is None:
- return mock
+ return
func, sig = result
def checksig(*args, **kwargs):
sig.bind(*args, **kwargs)
@@ -279,19 +301,17 @@ def _set_signature(mock, original, instance=False):
return mock(*args, **kwargs)""" % name
six.exec_(src, context)
funcopy = context[name]
- _setup_func(funcopy, mock, sig)
+ _setup_func(funcopy, mock)
return funcopy
-def _setup_func(funcopy, mock, sig):
+def _setup_func(funcopy, mock):
funcopy.mock = mock
- def assert_called(*args, **kwargs):
- return mock.assert_called(*args, **kwargs)
- def assert_not_called(*args, **kwargs):
- return mock.assert_not_called(*args, **kwargs)
- def assert_called_once(*args, **kwargs):
- return mock.assert_called_once(*args, **kwargs)
+ # can't use isinstance with mocks
+ if not _is_instance_mock(mock):
+ return
+
def assert_called_with(*args, **kwargs):
return mock.assert_called_with(*args, **kwargs)
def assert_called_once_with(*args, **kwargs):
@@ -324,10 +344,6 @@ def _setup_func(funcopy, mock, sig):
funcopy.assert_has_calls = assert_has_calls
funcopy.assert_any_call = assert_any_call
funcopy.reset_mock = reset_mock
- funcopy.assert_called = assert_called
- funcopy.assert_not_called = assert_not_called
- funcopy.assert_called_once = assert_called_once
- funcopy.__signature__ = sig
mock._mock_delegate = funcopy
@@ -344,13 +360,6 @@ class _SentinelObject(object):
def __repr__(self):
return 'sentinel.%s' % self.name
- def __reduce__(self):
- return _unpickle_sentinel, (self.name, )
-
-
-def _unpickle_sentinel(name):
- return getattr(sentinel, name)
-
class _Sentinel(object):
"""Access attributes to return a named object, usable as a sentinel."""
@@ -376,15 +385,21 @@ class OldStyleClass:
ClassType = type(OldStyleClass)
+def _copy(value):
+ if type(value) in (dict, list, tuple, set):
+ return type(value)(value)
+ return value
+
+
ClassTypes = (type,)
if six.PY2:
ClassTypes = (type, ClassType)
-_allowed_names = {
+_allowed_names = set((
'return_value', '_mock_return_value', 'side_effect',
'_mock_side_effect', '_mock_parent', '_mock_new_parent',
'_mock_name', '_mock_new_name'
-}
+))
def _delegating_property(name):
@@ -427,14 +442,6 @@ class _CallList(list):
def _check_and_set_parent(parent, value, name, new_name):
- # function passed to create_autospec will have mock
- # attribute attached to which parent must be set
- if isinstance(value, FunctionTypes):
- try:
- value = value.mock
- except AttributeError:
- pass
-
if not _is_instance_mock(value):
return False
if ((value._mock_name or value._mock_new_name) or
@@ -462,6 +469,8 @@ def _check_and_set_parent(parent, value, name, new_name):
class _MockIter(object):
def __init__(self, obj):
self.obj = iter(obj)
+ def __iter__(self):
+ return self
def __next__(self):
return next(self.obj)
@@ -498,7 +507,6 @@ class NonCallableMock(Base):
__dict__['_mock_name'] = name
__dict__['_mock_new_name'] = _new_name
__dict__['_mock_new_parent'] = _new_parent
- __dict__['_mock_sealed'] = False
if spec_set is not None:
spec = spec_set
@@ -561,7 +569,7 @@ class NonCallableMock(Base):
if isinstance(spec, ClassTypes):
_spec_class = spec
else:
- _spec_class = type(spec)
+ _spec_class = _get_class(spec)
res = _get_signature_object(spec,
_spec_as_instance, _eat_self)
_spec_signature = res and res[1]
@@ -635,7 +643,7 @@ class NonCallableMock(Base):
side_effect = property(__get_side_effect, __set_side_effect)
- def reset_mock(self, visited=None, return_value=False, side_effect=False):
+ def reset_mock(self, visited=None):
"Restore the mock object to its initial state."
if visited is None:
visited = []
@@ -650,13 +658,8 @@ class NonCallableMock(Base):
self.call_args_list = _CallList()
self.method_calls = _CallList()
- if return_value:
- self._mock_return_value = DEFAULT
- if side_effect:
- self._mock_side_effect = None
-
for child in self._mock_children.values():
- if isinstance(child, _SpecState) or child is _deleted:
+ if isinstance(child, _SpecState):
continue
child.reset_mock(visited)
@@ -725,7 +728,7 @@ class NonCallableMock(Base):
return result
- def _extract_mock_name(self):
+ def __repr__(self):
_name_list = [self._mock_new_name]
_parent = self._mock_new_parent
last = self
@@ -733,7 +736,7 @@ class NonCallableMock(Base):
dot = '.'
if _name_list == ['()']:
dot = ''
-
+ seen = set()
while _parent is not None:
last = _parent
@@ -744,16 +747,18 @@ class NonCallableMock(Base):
_parent = _parent._mock_new_parent
+ # use ids here so as not to call __hash__ on the mocks
+ if id(_parent) in seen:
+ break
+ seen.add(id(_parent))
+
_name_list = list(reversed(_name_list))
_first = last._mock_name or 'mock'
if len(_name_list) > 1:
if _name_list[1] not in ('()', '().'):
_first += '.'
_name_list[0] = _first
- return ''.join(_name_list)
-
- def __repr__(self):
- name = self._extract_mock_name()
+ name = ''.join(_name_list)
name_string = ''
if name not in ('mock', 'mock.'):
@@ -765,7 +770,7 @@ class NonCallableMock(Base):
if self._spec_set:
spec_string = ' spec_set=%r'
spec_string = spec_string % self._spec_class.__name__
- return "<{}{}{} id='{}'>".format(
+ return "<%s%s%s id='%s'>" % (
type(self).__name__,
name_string,
spec_string,
@@ -782,17 +787,14 @@ class NonCallableMock(Base):
extras = self._mock_methods or []
from_type = dir(type(self))
from_dict = list(self.__dict__)
- from_child_mocks = [
- m_name for m_name, m_value in self._mock_children.items()
- if m_value is not _deleted]
if mock.FILTER_DIR:
# object.__dir__ is not in 2.7
from_type = [e for e in from_type if not e.startswith('_')]
from_dict = [e for e in from_dict if not e.startswith('_') or
_is_magic(e)]
-
- return sorted(set(extras + from_type + from_dict + from_child_mocks))
+ return sorted(set(extras + from_type + from_dict +
+ list(self._mock_children)))
def __setattr__(self, name, value):
@@ -826,11 +828,6 @@ class NonCallableMock(Base):
else:
if _check_and_set_parent(self, value, name, name):
self._mock_children[name] = value
-
- if self._mock_sealed and not hasattr(self, name):
- mock_name = self._extract_mock_name()+'.'+name
- raise AttributeError('Cannot set '+mock_name)
-
return object.__setattr__(self, name, value)
@@ -842,10 +839,11 @@ class NonCallableMock(Base):
# not set on the instance itself
return
- obj = self._mock_children.get(name, _missing)
if name in self.__dict__:
- _safe_super(NonCallableMock, self).__delattr__(name)
- elif obj is _deleted:
+ object.__delattr__(self, name)
+
+ obj = self._mock_children.get(name, _missing)
+ if obj is _deleted:
raise AttributeError(name)
if obj is not _missing:
del self._mock_children[name]
@@ -858,16 +856,18 @@ class NonCallableMock(Base):
def _format_mock_failure_message(self, args, kwargs):
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nActual call: %s'
expected_string = self._format_mock_call_signature(args, kwargs)
call_args = self.call_args
+ if len(call_args) == 3:
+ call_args = call_args[1:]
actual_string = self._format_mock_call_signature(*call_args)
return message % (expected_string, actual_string)
def _call_matcher(self, _call):
"""
- Given a call (or simply an (args, kwargs) tuple), return a
+ Given a call (or simply a (args, kwargs) tuple), return a
comparison key suitable for matching with other calls.
This is a best effort method which relies on the spec's signature,
if available, or falls back on the arguments themselves.
@@ -892,10 +892,8 @@ class NonCallableMock(Base):
"""
self = _mock_self
if self.call_count != 0:
- msg = ("Expected '%s' to not have been called. Called %s times.%s"
- % (self._mock_name or 'mock',
- self.call_count,
- self._calls_repr()))
+ msg = ("Expected '%s' to not have been called. Called %s times." %
+ (self._mock_name or 'mock', self.call_count))
raise AssertionError(msg)
def assert_called(_mock_self):
@@ -912,10 +910,8 @@ class NonCallableMock(Base):
"""
self = _mock_self
if not self.call_count == 1:
- msg = ("Expected '%s' to have been called once. Called %s times.%s"
- % (self._mock_name or 'mock',
- self.call_count,
- self._calls_repr()))
+ msg = ("Expected '%s' to have been called once. Called %s times." %
+ (self._mock_name or 'mock', self.call_count))
raise AssertionError(msg)
def assert_called_with(_mock_self, *args, **kwargs):
@@ -926,16 +922,13 @@ class NonCallableMock(Base):
self = _mock_self
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
- actual = 'not called.'
- error_message = ('expected call not found.\nExpected: %s\nActual: %s'
- % (expected, actual))
- raise AssertionError(error_message)
+ raise AssertionError('Expected call: %s\nNot called' % (expected,))
def _error_message(cause):
msg = self._format_mock_failure_message(args, kwargs)
if six.PY2 and cause is not None:
# Tack on some diagnostics for Python without __cause__
- msg = '{}\n{}'.format(msg, str(cause))
+ msg = '%s\n%s' % (msg, str(cause))
return msg
expected = self._call_matcher((args, kwargs))
actual = self._call_matcher(self.call_args)
@@ -945,14 +938,12 @@ class NonCallableMock(Base):
def assert_called_once_with(_mock_self, *args, **kwargs):
- """assert that the mock was called exactly once and that that call was
- with the specified arguments."""
+ """assert that the mock was called exactly once and with the specified
+ arguments."""
self = _mock_self
if not self.call_count == 1:
- msg = ("Expected '%s' to be called once. Called %s times.%s"
- % (self._mock_name or 'mock',
- self.call_count,
- self._calls_repr()))
+ msg = ("Expected '%s' to be called once. Called %s times." %
+ (self._mock_name or 'mock', self.call_count))
raise AssertionError(msg)
return self.assert_called_with(*args, **kwargs)
@@ -973,8 +964,8 @@ class NonCallableMock(Base):
if not any_order:
if expected not in all_calls:
six.raise_from(AssertionError(
- 'Calls not found.\nExpected: %r%s'
- % (_CallList(calls), self._calls_repr(prefix="Actual"))
+ 'Calls not found.\nExpected: %r\n'
+ 'Actual: %r' % (_CallList(calls), self.mock_calls)
), cause)
return
@@ -988,9 +979,7 @@ class NonCallableMock(Base):
not_found.append(kall)
if not_found:
six.raise_from(AssertionError(
- '%r does not contain all of %r in its call list, '
- 'found %r instead' % (self._mock_name or 'mock',
- tuple(not_found), all_calls)
+ '%r not all found in call list' % (tuple(not_found),)
), cause)
@@ -1026,28 +1015,9 @@ class NonCallableMock(Base):
klass = Mock
else:
klass = _type.__mro__[1]
-
- if self._mock_sealed:
- attribute = "." + kw["name"] if "name" in kw else "()"
- mock_name = self._extract_mock_name() + attribute
- raise AttributeError(mock_name)
-
return klass(**kw)
- def _calls_repr(self, prefix="Calls"):
- """Renders self.mock_calls as a string.
-
- Example: "\nCalls: [call(1), call(2)]."
-
- If self.mock_calls is empty, an empty string is returned. The
- output will be truncated if very long.
- """
- if not self.mock_calls:
- return ""
- return "\n"+prefix+": "+safe_repr(self.mock_calls)+"."
-
-
def _try_iter(obj):
if obj is None:
@@ -1096,68 +1066,73 @@ class CallableMixin(Base):
self = _mock_self
self.called = True
self.call_count += 1
+ _new_name = self._mock_new_name
+ _new_parent = self._mock_new_parent
- # handle call_args
_call = _Call((args, kwargs), two=True)
self.call_args = _call
self.call_args_list.append(_call)
+ self.mock_calls.append(_Call(('', args, kwargs)))
- # initial stuff for method_calls:
+ seen = set()
+ skip_next_dot = _new_name == '()'
do_method_calls = self._mock_parent is not None
- method_call_name = self._mock_name
+ name = self._mock_name
+ while _new_parent is not None:
+ this_mock_call = _Call((_new_name, args, kwargs))
+ if _new_parent._mock_new_name:
+ dot = '.'
+ if skip_next_dot:
+ dot = ''
- # initial stuff for mock_calls:
- mock_call_name = self._mock_new_name
- is_a_call = mock_call_name == '()'
- self.mock_calls.append(_Call(('', args, kwargs)))
+ skip_next_dot = False
+ if _new_parent._mock_new_name == '()':
+ skip_next_dot = True
- # follow up the chain of mocks:
- _new_parent = self._mock_new_parent
- while _new_parent is not None:
+ _new_name = _new_parent._mock_new_name + dot + _new_name
- # handle method_calls:
if do_method_calls:
- _new_parent.method_calls.append(_Call((method_call_name, args, kwargs)))
+ if _new_name == name:
+ this_method_call = this_mock_call
+ else:
+ this_method_call = _Call((name, args, kwargs))
+ _new_parent.method_calls.append(this_method_call)
+
do_method_calls = _new_parent._mock_parent is not None
if do_method_calls:
- method_call_name = _new_parent._mock_name + '.' + method_call_name
+ name = _new_parent._mock_name + '.' + name
- # handle mock_calls:
- this_mock_call = _Call((mock_call_name, args, kwargs))
_new_parent.mock_calls.append(this_mock_call)
-
- if _new_parent._mock_new_name:
- if is_a_call:
- dot = ''
- else:
- dot = '.'
- is_a_call = _new_parent._mock_new_name == '()'
- mock_call_name = _new_parent._mock_new_name + dot + mock_call_name
-
- # follow the parental chain:
_new_parent = _new_parent._mock_new_parent
+ # use ids here so as not to call __hash__ on the mocks
+ _new_parent_id = id(_new_parent)
+ if _new_parent_id in seen:
+ break
+ seen.add(_new_parent_id)
+
+ ret_val = DEFAULT
effect = self.side_effect
if effect is not None:
if _is_exception(effect):
raise effect
- elif not _callable(effect):
+
+ if not _callable(effect):
result = next(effect)
if _is_exception(result):
raise result
- else:
- result = effect(*args, **kwargs)
-
- if result is not DEFAULT:
+ if result is DEFAULT:
+ result = self.return_value
return result
- if self._mock_return_value is not DEFAULT:
- return self.return_value
+ ret_val = effect(*args, **kwargs)
- if self._mock_wraps is not None:
+ if (self._mock_wraps is not None and
+ self._mock_return_value is DEFAULT):
return self._mock_wraps(*args, **kwargs)
-
- return self.return_value
+ if ret_val is DEFAULT:
+ ret_val = self.return_value
+ return ret_val
@@ -1365,7 +1340,7 @@ class _patch(object):
if not self.create and original is DEFAULT:
raise AttributeError(
- "{} does not have the attribute {!r}".format(target, name)
+ "%s does not have the attribute %r" % (target, name)
)
return original, local
@@ -1499,7 +1474,7 @@ class _patch(object):
def __exit__(self, *exc_info):
"""Undo the patch."""
if not _is_started(self):
- return
+ raise RuntimeError('stop called on unstarted patcher')
if self.is_local and self.temp_original is not DEFAULT:
setattr(self.target, self.attribute, self.temp_original)
@@ -1729,6 +1704,8 @@ class _patch_dict(object):
"""
def __init__(self, in_dict, values=(), clear=False, **kwargs):
+ if isinstance(in_dict, basestring):
+ in_dict = _importer(in_dict)
self.in_dict = in_dict
# support any argument supported by dict(...) constructor
self.values = dict(values)
@@ -1769,8 +1746,6 @@ class _patch_dict(object):
def _patch_dict(self):
values = self.values
- if isinstance(self.in_dict, basestring):
- self.in_dict = _importer(self.in_dict)
in_dict = self.in_dict
clear = self.clear
@@ -1848,7 +1823,7 @@ magic_methods = (
# because there is no idivmod
"divmod rdivmod neg pos abs invert "
"complex int float index "
- "round trunc floor ceil "
+ "trunc floor ceil "
)
numerics = (
@@ -1861,8 +1836,6 @@ right = ' '.join('r%s' % n for n in numerics.split())
extra = ''
if six.PY3:
extra = 'bool next '
- if sys.version_info >= (3, 6):
- extra += 'fspath '
else:
extra = 'unicode long nonzero oct hex truediv rtruediv '
@@ -1870,14 +1843,13 @@ else:
# (as they are metaclass methods)
# __del__ is not supported at all as it causes problems if it exists
-_non_defaults = {
+_non_defaults = set((
'__cmp__', '__getslice__', '__setslice__', '__coerce__', # <3.x
'__get__', '__set__', '__delete__', '__reversed__', '__missing__',
'__reduce__', '__reduce_ex__', '__getinitargs__', '__getnewargs__',
'__getstate__', '__setstate__', '__getformat__', '__setformat__',
'__repr__', '__dir__', '__subclasses__', '__format__',
- '__getnewargs_ex__',
-}
+))
def _get_method(name, func):
@@ -1888,26 +1860,25 @@ def _get_method(name, func):
return method
-_magics = {
+_magics = set(
'__%s__' % method for method in
' '.join([magic_methods, numerics, inplace, right, extra]).split()
-}
+)
_all_magics = _magics | _non_defaults
-_unsupported_magics = {
+_unsupported_magics = set((
'__getattr__', '__setattr__',
- '__init__', '__new__', '__prepare__',
+ '__init__', '__new__', '__prepare__'
'__instancecheck__', '__subclasscheck__',
'__del__'
-}
+))
_calculate_return_value = {
'__hash__': lambda self: object.__hash__(self),
'__str__': lambda self: object.__str__(self),
'__sizeof__': lambda self: object.__sizeof__(self),
'__unicode__': lambda self: unicode(object.__str__(self)),
- '__fspath__': lambda self: type(self).__name__+'/'+self._extract_mock_name()+'/'+str(id(self)),
}
_return_values = {
@@ -1935,18 +1906,14 @@ def _get_eq(self):
ret_val = self.__eq__._mock_return_value
if ret_val is not DEFAULT:
return ret_val
- if self is other:
- return True
- return NotImplemented
+ return self is other
return __eq__
def _get_ne(self):
def __ne__(other):
if self.__ne__._mock_return_value is not DEFAULT:
return DEFAULT
- if self is other:
- return False
- return NotImplemented
+ return self is not other
return __ne__
def _get_iter(self):
@@ -1980,7 +1947,6 @@ def _set_return_value(mock, method, name):
except AttributeError:
# XXXX why do we return AttributeError here?
# set it as a side_effect instead?
- # Answer: it makes magic mocks work on pypy?!
return_value = AttributeError(name)
method.return_value = return_value
return
@@ -2061,6 +2027,10 @@ class MagicProxy(object):
self.name = name
self.parent = parent
+ def __call__(self, *args, **kwargs):
+ m = self.create_mock()
+ return m(*args, **kwargs)
+
def create_mock(self):
entry = self.name
parent = self.parent
@@ -2105,7 +2075,7 @@ def _format_call_signature(name, args, kwargs):
return item
kwargs_string = ', '.join([
- '{}={!r}'.format(encode_item(key), value) for key, value in sorted(kwargs.items())
+ '%s=%r' % (encode_item(key), value) for key, value in sorted(kwargs.items())
])
if args_string:
formatted_args = args_string
@@ -2137,8 +2107,9 @@ class _Call(tuple):
If the _Call has no name then it will match any name.
"""
- def __new__(cls, value=(), name='', parent=None, two=False,
+ def __new__(cls, value=(), name=None, parent=None, two=False,
from_kall=True):
+ name = ''
args = ()
kwargs = {}
_len = len(value)
@@ -2171,9 +2142,9 @@ class _Call(tuple):
def __init__(self, value=(), name=None, parent=None, two=False,
from_kall=True):
- self._mock_name = name
- self._mock_parent = parent
- self._mock_from_kall = from_kall
+ self.name = name
+ self.parent = parent
+ self.from_kall = from_kall
def __eq__(self, other):
@@ -2190,10 +2161,6 @@ class _Call(tuple):
else:
self_name, self_args, self_kwargs = self
- if (getattr(self, '_mock_parent', None) and getattr(other, '_mock_parent', None)
- and self._mock_parent != other._mock_parent):
- return False
-
other_name = ''
if len_other == 0:
other_args, other_kwargs = (), {}
@@ -2237,17 +2204,17 @@ class _Call(tuple):
__hash__ = None
def __call__(self, *args, **kwargs):
- if self._mock_name is None:
+ if self.name is None:
return _Call(('', args, kwargs), name='()')
- name = self._mock_name + '()'
- return _Call((self._mock_name, args, kwargs), name=name, parent=self)
+ name = self.name + '()'
+ return _Call((self.name, args, kwargs), name=name, parent=self)
def __getattr__(self, attr):
- if self._mock_name is None:
+ if self.name is None:
return _Call(name=attr, from_kall=False)
- name = '{}.{}'.format(self._mock_name, attr)
+ name = '%s.%s' % (self.name, attr)
return _Call(name=name, parent=self, from_kall=False)
@@ -2257,25 +2224,9 @@ class _Call(tuple):
def index(self, *args, **kwargs):
return self.__getattr__('index')(*args, **kwargs)
- def _get_call_arguments(self):
- if len(self) == 2:
- args, kwargs = self
- else:
- name, args, kwargs = self
-
- return args, kwargs
-
- @property
- def args(self):
- return self._get_call_arguments()[0]
-
- @property
- def kwargs(self):
- return self._get_call_arguments()[1]
-
def __repr__(self):
- if not self._mock_from_kall:
- name = self._mock_name or 'call'
+ if not self.from_kall:
+ name = self.name or 'call'
if name.startswith('()'):
name = 'call%s' % name
return name
@@ -2301,9 +2252,9 @@ class _Call(tuple):
vals = []
thing = self
while thing is not None:
- if thing._mock_from_kall:
+ if thing.from_kall:
vals.append(thing)
- thing = thing._mock_parent
+ thing = thing.parent
return _CallList(reversed(vals))
@@ -2349,7 +2300,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
_kwargs.update(kwargs)
Klass = MagicMock
- if inspect.isdatadescriptor(spec):
+ if type(spec) in DescriptorTypes:
# descriptors don't have a spec
# because we don't know what type they return
_kwargs = {}
@@ -2383,12 +2334,6 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
_name='()', _parent=mock)
for entry in dir(spec):
-
- # This are __ and so treated as magic on Py3, on Py2 we need to
- # explicitly ignore them:
- if six.PY2 and (entry.startswith('im_') or entry.startswith('func_')):
- continue
-
if _is_magic(entry):
# MagicMock already does the useful magic methods for us
continue
@@ -2464,10 +2409,19 @@ def _must_skip(spec, entry, is_type):
else:
return False
- # function is a dynamically provided attribute
+ # shouldn't get here unless function is a dynamically provided attribute
+ # XXXX untested behaviour
return is_type
+def _get_class(obj):
+ try:
+ return obj.__class__
+ except AttributeError:
+ # it is possible for objects to have no __class__
+ return type(obj)
+
+
class _SpecState(object):
def __init__(self, spec, spec_set=False, parent=None,
@@ -2494,13 +2448,25 @@ MethodWrapperTypes = (
file_spec = None
-
-def _to_stream(read_data):
- if isinstance(read_data, bytes):
- return io.BytesIO(read_data)
+def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b'\n' if isinstance(read_data, bytes) else '\n'
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
else:
- return io.StringIO(read_data)
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+ for line in data_as_list:
+ yield line
def mock_open(mock=None, read_data=''):
"""
@@ -2511,35 +2477,27 @@ def mock_open(mock=None, read_data=''):
default) then a `MagicMock` will be created for you, with the API limited
to methods or attributes available on standard file handles.
- `read_data` is a string for the `read`, `readline` and `readlines` of the
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
file handle to return. This is an empty string by default.
"""
- _read_data = _to_stream(read_data)
- _state = [_read_data, None]
-
def _readlines_side_effect(*args, **kwargs):
if handle.readlines.return_value is not None:
return handle.readlines.return_value
- return _state[0].readlines(*args, **kwargs)
+ return list(_state[0])
def _read_side_effect(*args, **kwargs):
if handle.read.return_value is not None:
return handle.read.return_value
- return _state[0].read(*args, **kwargs)
-
- def _readline_side_effect(*args, **kwargs):
- for item in _iter_side_effect():
- yield item
- while True:
- yield _state[0].readline(*args, **kwargs)
+ return type(read_data)().join(_state[0])
- def _iter_side_effect():
+ def _readline_side_effect():
if handle.readline.return_value is not None:
while True:
yield handle.readline.return_value
for line in _state[0]:
yield line
+
global file_spec
if file_spec is None:
# set on first use
@@ -2555,6 +2513,8 @@ def mock_open(mock=None, read_data=''):
handle = MagicMock(spec=file_spec)
handle.__enter__.return_value = handle
+ _state = [_iterate_read_data(read_data), None]
+
handle.write.return_value = None
handle.read.return_value = None
handle.readline.return_value = None
@@ -2564,10 +2524,9 @@ def mock_open(mock=None, read_data=''):
_state[1] = _readline_side_effect()
handle.readline.side_effect = _state[1]
handle.readlines.side_effect = _readlines_side_effect
- handle.__iter__.side_effect = _iter_side_effect
def reset_data(*args, **kwargs):
- _state[0] = _to_stream(read_data)
+ _state[0] = _iterate_read_data(read_data)
if handle.readline.side_effect == _state[1]:
# Only reset the side effect if the user hasn't overridden it.
_state[1] = _readline_side_effect()
@@ -2595,25 +2554,3 @@ class PropertyMock(Mock):
return self()
def __set__(self, obj, val):
self(val)
-
-
-def seal(mock):
- """Disable the automatic generation of child mocks.
-
- Given an input Mock, seals it to ensure no further mocks will be generated
- when accessing an attribute that was not already defined.
-
- The operation recursively seals the mock passed in, meaning that
- the mock itself, any mocks generated by accessing one of its attributes,
- and all assigned mocks without a name or spec will be sealed.
- """
- mock._mock_sealed = True
- for attr in dir(mock):
- try:
- m = getattr(mock, attr)
- except AttributeError:
- continue
- if not isinstance(m, NonCallableMock):
- continue
- if m._mock_new_parent is mock:
- seal(m)
diff --git a/mock/tests/conftest.py b/mock/tests/conftest.py
deleted file mode 100644
index 78831f6..0000000
--- a/mock/tests/conftest.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import six
-
-
-def pytest_ignore_collect(path):
- if 'py3' in path.basename and six.PY2:
- return True
diff --git a/mock/tests/support.py b/mock/tests/support.py
index d57a372..c7ad20b 100644
--- a/mock/tests/support.py
+++ b/mock/tests/support.py
@@ -1,10 +1,3 @@
-import contextlib
-import sys
-
-
-target = {'foo': 'FOO'}
-
-
def is_instance(obj, klass):
"""Version of is_instance that doesn't access __class__"""
return issubclass(type(obj), klass)
@@ -13,34 +6,9 @@ def is_instance(obj, klass):
class SomeClass(object):
class_attribute = None
- def wibble(self): pass
+ def wibble(self):
+ pass
class X(object):
pass
-
-
-@contextlib.contextmanager
-def uncache(*names):
- """Uncache a module from sys.modules.
-
- A basic sanity check is performed to prevent uncaching modules that either
- cannot/shouldn't be uncached.
-
- """
- for name in names:
- if name in ('sys', 'marshal', 'imp'):
- raise ValueError(
- "cannot uncache {0}".format(name))
- try:
- del sys.modules[name]
- except KeyError:
- pass
- try:
- yield
- finally:
- for name in names:
- try:
- del sys.modules[name]
- except KeyError:
- pass
diff --git a/mock/tests/testcallable.py b/mock/tests/testcallable.py
index 729947e..10acdc3 100644
--- a/mock/tests/testcallable.py
+++ b/mock/tests/testcallable.py
@@ -2,7 +2,7 @@
# E-mail: fuzzyman AT voidspace DOT org DOT uk
# http://www.voidspace.org.uk/python/mock/
-import unittest
+import unittest2 as unittest
from mock.tests.support import is_instance, X, SomeClass
from mock import (
@@ -27,7 +27,7 @@ class TestCallable(unittest.TestCase):
self.assertIn(mock.__class__.__name__, repr(mock))
- def test_hierarchy(self):
+ def test_heirarchy(self):
self.assertTrue(issubclass(MagicMock, Mock))
self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock))
@@ -98,7 +98,8 @@ class TestCallable(unittest.TestCase):
def test_patch_spec_callable_class(self):
class CallableX(X):
- def __call__(self): pass
+ def __call__(self):
+ pass
class Sub(CallableX):
pass
@@ -107,7 +108,8 @@ class TestCallable(unittest.TestCase):
pass
class OldStyle:
- def __call__(self): pass
+ def __call__(self):
+ pass
class OldStyleSub(OldStyle):
pass
diff --git a/mock/tests/testhelpers.py b/mock/tests/testhelpers.py
index d56a47f..a87df1b 100644
--- a/mock/tests/testhelpers.py
+++ b/mock/tests/testhelpers.py
@@ -1,32 +1,25 @@
# Copyright (C) 2007-2012 Michael Foord & the mock team
# E-mail: fuzzyman AT voidspace DOT org DOT uk
# http://www.voidspace.org.uk/python/mock/
-import socket
-import inspect
import six
-import sys
-import time
-import unittest
+import unittest2 as unittest
from mock import (
call, create_autospec, MagicMock,
Mock, ANY, patch, PropertyMock
)
-from mock.mock import _Call, _CallList, _callable
+from mock.mock import _Call, _CallList
from datetime import datetime
-from functools import partial
-
-
-if six.PY2:
- import funcsigs
-
class SomeClass(object):
- def one(self, a, b): pass
- def two(self): pass
- def three(self, a=None): pass
+ def one(self, a, b):
+ pass
+ def two(self):
+ pass
+ def three(self, a=None):
+ pass
@@ -57,9 +50,12 @@ class AnyTest(unittest.TestCase):
def test_any_mock_calls_comparison_order(self):
mock = Mock()
+ d = datetime.now()
class Foo(object):
- def __eq__(self, other): pass
- def __ne__(self, other): pass
+ def __eq__(self, other):
+ return False
+ def __ne__(self, other):
+ return True
for d in datetime.now(), Foo():
mock.reset_mock()
@@ -152,8 +148,6 @@ class CallTest(unittest.TestCase):
self.assertEqual(args, ('foo', (1, 2, 3)))
self.assertEqual(args, ('foo', (1, 2, 3), {}))
self.assertEqual(args, ((1, 2, 3), {}))
- self.assertEqual(args.args, (1, 2, 3))
- self.assertEqual(args.kwargs, {})
def test_named_call_with_args(self):
@@ -161,8 +155,6 @@ class CallTest(unittest.TestCase):
self.assertEqual(args, ('foo', (1, 2, 3)))
self.assertEqual(args, ('foo', (1, 2, 3), {}))
- self.assertEqual(args.args, (1, 2, 3))
- self.assertEqual(args.kwargs, {})
self.assertNotEqual(args, ((1, 2, 3),))
self.assertNotEqual(args, ((1, 2, 3), {}))
@@ -175,8 +167,6 @@ class CallTest(unittest.TestCase):
self.assertEqual(args, ('foo', dict(a=3, b=4)))
self.assertEqual(args, ('foo', (), dict(a=3, b=4)))
self.assertEqual(args, ((), dict(a=3, b=4)))
- self.assertEqual(args.args, ())
- self.assertEqual(args.kwargs, dict(a=3, b=4))
def test_named_call_with_kwargs(self):
@@ -184,8 +174,6 @@ class CallTest(unittest.TestCase):
self.assertEqual(args, ('foo', dict(a=3, b=4)))
self.assertEqual(args, ('foo', (), dict(a=3, b=4)))
- self.assertEqual(args.args, ())
- self.assertEqual(args.kwargs, dict(a=3, b=4))
self.assertNotEqual(args, (dict(a=3, b=4),))
self.assertNotEqual(args, ((), dict(a=3, b=4)))
@@ -193,7 +181,6 @@ class CallTest(unittest.TestCase):
def test_call_with_args_call_empty_name(self):
args = _Call(((1, 2, 3), {}))
-
self.assertEqual(args, call(1, 2, 3))
self.assertEqual(call(1, 2, 3), args)
self.assertIn(call(1, 2, 3), [args])
@@ -286,22 +273,6 @@ class CallTest(unittest.TestCase):
self.assertEqual(mock.mock_calls, last_call.call_list())
- def test_extended_not_equal(self):
- a = call(x=1).foo
- b = call(x=2).foo
- self.assertEqual(a, a)
- self.assertEqual(b, b)
- self.assertNotEqual(a, b)
-
-
- def test_nested_calls_not_equal(self):
- a = call(x=1).foo().bar
- b = call(x=2).foo().bar
- self.assertEqual(a, a)
- self.assertEqual(b, b)
- self.assertNotEqual(a, b)
-
-
def test_call_list(self):
mock = MagicMock()
mock(1)
@@ -341,11 +312,6 @@ class CallTest(unittest.TestCase):
other_args = _Call(((1, 2), {'a': 3}))
self.assertEqual(args, other_args)
- def test_call_with_name(self):
- self.assertEqual(_Call((), 'foo')[0], 'foo')
- self.assertEqual(_Call((('bar', 'barz'),),)[0], '')
- self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '')
-
class SpecSignatureTest(unittest.TestCase):
@@ -384,7 +350,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_create_autospec_return_value(self):
- def f(): pass
+ def f():
+ pass
mock = create_autospec(f, return_value='foo')
self.assertEqual(mock(), 'foo')
@@ -404,7 +371,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_mocking_unbound_methods(self):
class Foo(object):
- def foo(self, foo): pass
+ def foo(self, foo):
+ pass
p = patch.object(Foo, 'foo')
mock_foo = p.start()
Foo().foo(1)
@@ -412,6 +380,23 @@ class SpecSignatureTest(unittest.TestCase):
mock_foo.assert_called_with(1)
+ @unittest.expectedFailure
+ def test_create_autospec_unbound_methods(self):
+ # see mock issue 128
+ class Foo(object):
+ def foo(self):
+ pass
+
+ klass = create_autospec(Foo)
+ instance = klass()
+ self.assertRaises(TypeError, instance.foo, 1)
+
+ # Note: no type checking on the "self" parameter
+ klass.foo(1)
+ klass.foo.assert_called_with(1)
+ self.assertRaises(TypeError, klass.foo)
+
+
def test_create_autospec_keyword_arguments(self):
class Foo(object):
a = 3
@@ -420,7 +405,7 @@ class SpecSignatureTest(unittest.TestCase):
@unittest.skipUnless(six.PY3, "Keyword only arguments Python 3 specific")
def test_create_autospec_keyword_only_arguments(self):
- func_def = "def foo(a, *, b=None): pass\n"
+ func_def = "def foo(a, *, b=None):\n pass\n"
namespace = {}
exec (func_def, namespace)
foo = namespace['foo']
@@ -435,7 +420,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_function_as_instance_attribute(self):
obj = SomeClass()
- def f(a): pass
+ def f(a):
+ pass
obj.f = f
mock = create_autospec(obj)
@@ -471,56 +457,13 @@ class SpecSignatureTest(unittest.TestCase):
self._check_someclass_mock(mock)
- @unittest.skipIf('PyPy' in sys.version,
- "This fails on pypy, "
- "see https://github.com/testing-cabal/mock/issues/452")
- def test_spec_has_descriptor_returning_function(self):
- class CrazyDescriptor(object):
- def __get__(self, obj, type_):
- if obj is None:
- return lambda x: None
-
- class MyClass(object):
- some_attr = CrazyDescriptor()
-
- mock = create_autospec(MyClass)
- mock.some_attr(1)
- with self.assertRaises(TypeError):
- mock.some_attr()
- with self.assertRaises(TypeError):
- mock.some_attr(1, 2)
-
- @unittest.skipIf(six.PY2, "object.__dir__ doesn't exist in Python 2")
- def test_spec_has_function_not_in_bases(self):
- class CrazyClass(object):
- def __dir__(self):
- return super(CrazyClass, self).__dir__() + ['crazy']
-
- def __getattr__(self, item):
- if item == 'crazy':
- return lambda x: x
- raise AttributeError(item)
-
- inst = CrazyClass()
- with self.assertRaises(AttributeError):
- inst.other
- self.assertEqual(inst.crazy(42), 42)
- mock = create_autospec(inst)
- mock.crazy(42)
- with self.assertRaises(TypeError):
- mock.crazy()
- with self.assertRaises(TypeError):
- mock.crazy(1, 2)
-
-
- @unittest.skipIf('PyPy' in sys.version and sys.version_info < (3, 0),
- "Fails on pypy2 due to incorrect signature for dict.pop from funcsigs")
def test_builtin_functions_types(self):
# we could replace builtin functions / methods with a function
# with *args / **kwargs signature. Using the builtin method type
# as a spec seems to work fairly well though.
class BuiltinSubclass(list):
- def bar(self, arg): pass
+ def bar(self, arg):
+ pass
sorted = sorted
attr = {}
@@ -594,13 +537,17 @@ class SpecSignatureTest(unittest.TestCase):
def test_descriptors(self):
class Foo(object):
@classmethod
- def f(cls, a, b): pass
+ def f(cls, a, b):
+ pass
@staticmethod
- def g(a, b): pass
+ def g(a, b):
+ pass
- class Bar(Foo): pass
+ class Bar(Foo):
+ pass
- class Baz(SomeClass, Bar): pass
+ class Baz(SomeClass, Bar):
+ pass
for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()):
mock = create_autospec(spec)
@@ -614,7 +561,8 @@ class SpecSignatureTest(unittest.TestCase):
@unittest.skipIf(six.PY3, "No old style classes in Python 3")
def test_old_style_classes(self):
class Foo:
- def f(self, a, b): pass
+ def f(self, a, b):
+ pass
class Bar(Foo):
g = Foo()
@@ -634,7 +582,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_recursive(self):
class A(object):
- def a(self): pass
+ def a(self):
+ pass
foo = 'foo bar baz'
bar = foo
@@ -656,9 +605,11 @@ class SpecSignatureTest(unittest.TestCase):
def test_spec_inheritance_for_classes(self):
class Foo(object):
- def a(self, x): pass
+ def a(self, x):
+ pass
class Bar(object):
- def f(self, y): pass
+ def f(self, y):
+ pass
class_mock = create_autospec(Foo)
@@ -738,7 +689,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_function(self):
- def f(a, b): pass
+ def f(a, b):
+ pass
mock = create_autospec(f)
self.assertRaises(TypeError, mock)
@@ -768,10 +720,9 @@ class SpecSignatureTest(unittest.TestCase):
def existing(a, b):
return a + b
- self.assertEqual(RaiserClass.existing(1, 2), 3)
s = create_autospec(RaiserClass)
self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3))
- self.assertEqual(s.existing(1, 2), s.existing.return_value)
+ s.existing(1, 2)
self.assertRaises(AttributeError, lambda: s.nonexisting)
# check we can fetch the raiser attribute and it has no spec
@@ -781,7 +732,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_signature_class(self):
class Foo(object):
- def __init__(self, a, b=3): pass
+ def __init__(self, a, b=3):
+ pass
mock = create_autospec(Foo)
@@ -796,7 +748,8 @@ class SpecSignatureTest(unittest.TestCase):
@unittest.skipIf(six.PY3, 'no old style classes in Python 3')
def test_signature_old_style_class(self):
class Foo:
- def __init__(self, a, b=3): pass
+ def __init__(self, a, b=3):
+ pass
mock = create_autospec(Foo)
@@ -831,8 +784,10 @@ class SpecSignatureTest(unittest.TestCase):
def test_signature_callable(self):
class Callable(object):
- def __init__(self, x, y): pass
- def __call__(self, a): pass
+ def __init__(self, x, y):
+ pass
+ def __call__(self, a):
+ pass
mock = create_autospec(Callable)
mock(1, 2)
@@ -888,7 +843,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_autospec_functions_with_self_in_odd_place(self):
class Foo(object):
- def f(a, self): pass
+ def f(a, self):
+ pass
a = create_autospec(Foo)
a.f(10)
@@ -902,7 +858,8 @@ class SpecSignatureTest(unittest.TestCase):
def test_autospec_property(self):
class Foo(object):
@property
- def foo(self): pass
+ def foo(self):
+ return 3
foo = create_autospec(Foo)
mock_property = foo.foo
@@ -929,140 +886,6 @@ class SpecSignatureTest(unittest.TestCase):
mock_slot.abc.assert_called_once_with(4, 5, 6)
- def test_autospec_data_descriptor(self):
- class Descriptor(object):
- def __init__(self, value):
- self.value = value
-
- def __get__(self, obj, cls=None):
- return self
-
- def __set__(self, obj, value): pass
-
- class MyProperty(property):
- pass
-
- class Foo(object):
- __slots__ = ['slot']
-
- @property
- def prop(self): pass
-
- @MyProperty
- def subprop(self): pass
-
- desc = Descriptor(42)
-
- foo = create_autospec(Foo)
-
- def check_data_descriptor(mock_attr):
- # Data descriptors don't have a spec.
- self.assertIsInstance(mock_attr, MagicMock)
- mock_attr(1, 2, 3)
- mock_attr.abc(4, 5, 6)
- mock_attr.assert_called_once_with(1, 2, 3)
- mock_attr.abc.assert_called_once_with(4, 5, 6)
-
- # property
- check_data_descriptor(foo.prop)
- # property subclass
- check_data_descriptor(foo.subprop)
- # class __slot__
- check_data_descriptor(foo.slot)
- # plain data descriptor
- check_data_descriptor(foo.desc)
-
-
- @unittest.skipIf('PyPy' in sys.version and sys.version_info > (3, 0),
- "See https://github.com/testing-cabal/mock/issues/452")
- def test_autospec_on_bound_builtin_function(self):
- meth = six.create_bound_method(time.ctime, time.time())
- self.assertIsInstance(meth(), str)
- mocked = create_autospec(meth)
-
- # no signature, so no spec to check against
- mocked()
- mocked.assert_called_once_with()
- mocked.reset_mock()
- mocked(4, 5, 6)
- mocked.assert_called_once_with(4, 5, 6)
-
- def test_autospec_socket(self):
- sock_class = create_autospec(socket.socket)
- self.assertRaises(TypeError, sock_class, foo=1)
-
-
- def test_autospec_getattr_partial_function(self):
- # bpo-32153 : getattr returning partial functions without
- # __name__ should not create AttributeError in create_autospec
- class Foo(object):
- def __getattr__(self, attribute):
- return partial(lambda name: name, attribute)
- proxy = Foo()
- autospec = create_autospec(proxy)
- self.assertFalse(hasattr(autospec, '__name__'))
-
-
- def test_spec_inspect_signature(self):
-
- def myfunc(x, y): pass
-
- mock = create_autospec(myfunc)
- mock(1, 2)
- mock(x=1, y=2)
-
- if six.PY2:
- self.assertEqual(funcsigs.signature(mock), funcsigs.signature(myfunc))
- else:
- self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc))
- self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)])
- self.assertRaises(TypeError, mock, 1)
-
-
- def test_spec_function_no_name(self):
- func = lambda: 'nope'
- mock = create_autospec(func)
- self.assertEqual(mock.__name__, 'funcopy')
-
-
- @unittest.skipIf(six.PY3, "Here to test our Py2 _isidentifier")
- def test_spec_function_has_identifier_name(self):
- func = lambda: 'nope'
- func.__name__ = 'global'
- mock = create_autospec(func)
- self.assertEqual(mock.__name__, 'funcopy')
-
-
- def test_spec_function_assert_has_calls(self):
- def f(a): pass
- mock = create_autospec(f)
- mock(1)
- mock.assert_has_calls([call(1)])
- with self.assertRaises(AssertionError):
- mock.assert_has_calls([call(2)])
-
-
- def test_spec_function_assert_any_call(self):
- def f(a): pass
- mock = create_autospec(f)
- mock(1)
- mock.assert_any_call(1)
- with self.assertRaises(AssertionError):
- mock.assert_any_call(2)
-
-
- def test_spec_function_reset_mock(self):
- def f(a): pass
- rv = Mock()
- mock = create_autospec(f, return_value=rv)
- mock(1)(2)
- self.assertEqual(mock.mock_calls, [call(1)])
- self.assertEqual(rv.mock_calls, [call(2)])
- mock.reset_mock()
- self.assertEqual(mock.mock_calls, [])
- self.assertEqual(rv.mock_calls, [])
-
-
class TestCallList(unittest.TestCase):
def test_args_list_contains_call_list(self):
@@ -1148,40 +971,5 @@ class TestCallList(unittest.TestCase):
self.assertNotIsInstance(returned, PropertyMock)
-class TestCallablePredicate(unittest.TestCase):
-
- def test_type(self):
- for obj in [str, bytes, int, list, tuple, SomeClass]:
- self.assertTrue(_callable(obj))
-
- def test_call_magic_method(self):
- class Callable:
- def __call__(self): pass
- instance = Callable()
- self.assertTrue(_callable(instance))
-
- def test_staticmethod(self):
- class WithStaticMethod:
- @staticmethod
- def staticfunc(): pass
- self.assertTrue(_callable(WithStaticMethod.staticfunc))
-
- def test_non_callable_staticmethod(self):
- class BadStaticMethod:
- not_callable = staticmethod(None)
- self.assertFalse(_callable(BadStaticMethod.not_callable))
-
- def test_classmethod(self):
- class WithClassMethod:
- @classmethod
- def classfunc(cls): pass
- self.assertTrue(_callable(WithClassMethod.classfunc))
-
- def test_non_callable_classmethod(self):
- class BadClassMethod:
- not_callable = classmethod(None)
- self.assertFalse(_callable(BadClassMethod.not_callable))
-
-
if __name__ == '__main__':
unittest.main()
diff --git a/mock/tests/testhelpers_py3.py b/mock/tests/testhelpers_py3.py
deleted file mode 100644
index 64d62f8..0000000
--- a/mock/tests/testhelpers_py3.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import inspect
-import unittest
-
-from mock import call, create_autospec
-
-
-class CallTest(unittest.TestCase):
-
-
- def test_spec_inspect_signature_annotations(self):
-
- def foo(a: int, b: int=10, *, c:int) -> int:
- return a + b + c
-
- self.assertEqual(foo(1, 2, c=3), 6)
- mock = create_autospec(foo)
- mock(1, 2, c=3)
- mock(1, c=3)
-
- self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo))
- self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
- self.assertRaises(TypeError, mock, 1)
- self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
diff --git a/mock/tests/testmagicmethods.py b/mock/tests/testmagicmethods.py
index f6c25fb..f47a202 100644
--- a/mock/tests/testmagicmethods.py
+++ b/mock/tests/testmagicmethods.py
@@ -11,13 +11,12 @@ except NameError:
unicode = str
long = int
-import math
-import os
+import inspect
import sys
import textwrap
-import unittest
import six
+import unittest2 as unittest
from mock import Mock, MagicMock
from mock.mock import _magics
@@ -303,7 +302,7 @@ class TestMockingMagicMethods(unittest.TestCase):
for entry in _magics:
self.assertTrue(hasattr(mock, entry))
- self.assertFalse(hasattr(mock, '__imaginary__'))
+ self.assertFalse(hasattr(mock, '__imaginery__'))
def test_magic_mock_equality(self):
@@ -331,16 +330,6 @@ class TestMockingMagicMethods(unittest.TestCase):
self.assertEqual(unicode(mock), object.__str__(mock))
self.assertIsInstance(unicode(mock), unicode)
self.assertTrue(bool(mock))
- self.assertEqual(math.trunc(mock), mock.__trunc__())
- if six.PY2:
- # These fall back to __float__ in Python 2:
- self.assertEqual(round(mock), 1.0)
- self.assertEqual(math.floor(mock), 1.0)
- self.assertEqual(math.ceil(mock), 1.0)
- else:
- self.assertEqual(round(mock), mock.__round__())
- self.assertEqual(math.floor(mock), mock.__floor__())
- self.assertEqual(math.ceil(mock), mock.__ceil__())
if six.PY2:
self.assertEqual(oct(mock), '1')
else:
@@ -362,20 +351,10 @@ class TestMockingMagicMethods(unittest.TestCase):
self.assertEqual(mock, object())
- def test_magic_methods_fspath(self):
- mock = MagicMock()
- if sys.version_info < (3, 6):
- self.assertRaises(AttributeError, lambda: mock.__fspath__)
- else:
- expected_path = mock.__fspath__()
- mock.reset_mock()
- self.assertEqual(os.fspath(mock), expected_path)
- mock.__fspath__.assert_called_once()
-
-
def test_magic_methods_and_spec(self):
class Iterable(object):
- def __iter__(self): pass
+ def __iter__(self):
+ pass
mock = Mock(spec=Iterable)
self.assertRaises(AttributeError, lambda: mock.__iter__)
@@ -399,7 +378,8 @@ class TestMockingMagicMethods(unittest.TestCase):
def test_magic_methods_and_spec_set(self):
class Iterable(object):
- def __iter__(self): pass
+ def __iter__(self):
+ pass
mock = Mock(spec_set=Iterable)
self.assertRaises(AttributeError, lambda: mock.__iter__)
@@ -425,7 +405,7 @@ class TestMockingMagicMethods(unittest.TestCase):
mock = MagicMock()
def set_setattr():
mock.__setattr__ = lambda self, name: None
- self.assertRaisesRegexp(AttributeError,
+ self.assertRaisesRegex(AttributeError,
"Attempting to set unsupported magic method '__setattr__'.",
set_setattr
)
@@ -535,7 +515,7 @@ class TestMockingMagicMethods(unittest.TestCase):
self.assertIsInstance(bar_direct, MagicMock)
# http://bugs.python.org/issue23310
- # Check if you can change behaviour of magic methods in MagicMock init
+ # Check if you can change behaviour of magic methds in MagicMock init
def test_magic_in_initialization(self):
m = MagicMock(**{'__str__.return_value': "12"})
self.assertEqual(str(m), "12")
diff --git a/mock/tests/testmock.py b/mock/tests/testmock.py
index 5f6045a..66323e9 100644
--- a/mock/tests/testmock.py
+++ b/mock/tests/testmock.py
@@ -4,20 +4,20 @@
import copy
import pickle
-import re
import sys
import tempfile
import six
-import unittest
+import unittest2 as unittest
import mock
-from mock.mock import (
+from mock import (
call, DEFAULT, patch, sentinel,
MagicMock, Mock, NonCallableMock,
- NonCallableMagicMock, _Call, _CallList,
+ NonCallableMagicMock,
create_autospec
)
+from mock.mock import _CallList
from mock.tests.support import is_instance
@@ -41,13 +41,16 @@ class Iter(object):
class Something(object):
- def meth(self, a, b, c, d=None): pass
+ def meth(self, a, b, c, d=None):
+ pass
@classmethod
- def cmeth(cls, a, b, c, d=None): pass
+ def cmeth(cls, a, b, c, d=None):
+ pass
@staticmethod
- def smeth(a, b, c, d=None): pass
+ def smeth(a, b, c, d=None):
+ pass
class Subclass(MagicMock):
@@ -103,21 +106,6 @@ class MockTest(unittest.TestCase):
"return value in constructor not honoured")
- def test_change_return_value_via_delegate(self):
- def f(): pass
- mock = create_autospec(f)
- mock.mock.return_value = 1
- self.assertEqual(mock(), 1)
-
-
- def test_change_side_effect_via_delegate(self):
- def f(): pass
- mock = create_autospec(f)
- mock.mock.side_effect = TypeError()
- with self.assertRaises(TypeError):
- mock()
-
-
def test_repr(self):
mock = Mock(name='foo')
self.assertIn('foo', repr(mock))
@@ -196,7 +184,8 @@ class MockTest(unittest.TestCase):
results = [1, 2, 3]
def effect():
return results.pop()
- def f(): pass
+ def f():
+ pass
mock = create_autospec(f)
mock.side_effect = [1, 2, 3]
@@ -211,11 +200,28 @@ class MockTest(unittest.TestCase):
def test_autospec_side_effect_exception(self):
# Test for issue 23661
- def f(): pass
+ def f():
+ pass
mock = create_autospec(f)
mock.side_effect = ValueError('Bazinga!')
- self.assertRaisesRegexp(ValueError, 'Bazinga!', mock)
+ self.assertRaisesRegex(ValueError, 'Bazinga!', mock)
+
+ @unittest.skipUnless('java' in sys.platform,
+ 'This test only applies to Jython')
+ def test_java_exception_side_effect(self):
+ import java
+ mock = Mock(side_effect=java.lang.RuntimeException("Boom!"))
+
+ # can't use assertRaises with java exceptions
+ try:
+ mock(1, 2, fish=3)
+ except java.lang.RuntimeException:
+ pass
+ else:
+ self.fail('java exception not raised')
+ mock.assert_called_with(1,2, fish=3)
+
def test_reset_mock(self):
parent = Mock()
@@ -284,10 +290,6 @@ class MockTest(unittest.TestCase):
self.assertEqual(mock.call_count, 1, "call_count incoreect")
self.assertEqual(mock.call_args, ((sentinel.Arg,), {}),
"call_args not set")
- self.assertEqual(mock.call_args.args, (sentinel.Arg,),
- "call_args not set")
- self.assertEqual(mock.call_args.kwargs, {},
- "call_args not set")
self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {})],
"call_args_list not initialised correctly")
@@ -321,35 +323,11 @@ class MockTest(unittest.TestCase):
])
self.assertEqual(mock.call_args,
((sentinel.Arg,), {"kw": sentinel.Kwarg}))
- self.assertEqual(mock.call_args.args, (sentinel.Arg,))
- self.assertEqual(mock.call_args.kwargs, {"kw": sentinel.Kwarg})
# Comparing call_args to a long sequence should not raise
# an exception. See issue 24857.
self.assertFalse(mock.call_args == "a long sequence")
-
- def test_calls_equal_with_any(self):
- # Check that equality and non-equality is consistent even when
- # comparing with mock.ANY
- mm = mock.MagicMock()
- self.assertTrue(mm == mm)
- self.assertFalse(mm != mm)
- self.assertFalse(mm == mock.MagicMock())
- self.assertTrue(mm != mock.MagicMock())
- self.assertTrue(mm == mock.ANY)
- self.assertFalse(mm != mock.ANY)
- self.assertTrue(mock.ANY == mm)
- self.assertFalse(mock.ANY != mm)
-
- call1 = mock.call(mock.MagicMock())
- call2 = mock.call(mock.ANY)
- self.assertTrue(call1 == call2)
- self.assertFalse(call1 != call2)
- self.assertTrue(call2 == call1)
- self.assertFalse(call2 != call1)
-
-
def test_assert_called_with(self):
mock = Mock()
mock()
@@ -365,14 +343,9 @@ class MockTest(unittest.TestCase):
mock.assert_called_with(1, 2, 3, a='fish', b='nothing')
- def test_assert_called_with_any(self):
- m = MagicMock()
- m(MagicMock())
- m.assert_called_with(mock.ANY)
-
-
def test_assert_called_with_function_spec(self):
- def f(a, b, c, d=None): pass
+ def f(a, b, c, d=None):
+ pass
mock = Mock(spec=f)
@@ -431,17 +404,10 @@ class MockTest(unittest.TestCase):
lambda: mock.assert_called_once_with('bob', 'bar', baz=2)
)
- def test_assert_called_once_with_call_list(self):
- m = Mock()
- m(1)
- m(2)
- self.assertRaisesRegexp(AssertionError,
- re.escape("Calls: [call(1), call(2)]"),
- lambda: m.assert_called_once_with(2))
-
def test_assert_called_once_with_function_spec(self):
- def f(a, b, c, d=None): pass
+ def f(a, b, c, d=None):
+ pass
mock = Mock(spec=f)
@@ -535,7 +501,7 @@ class MockTest(unittest.TestCase):
# this should be allowed
mock.something
- self.assertRaisesRegexp(
+ self.assertRaisesRegex(
AttributeError,
"Mock object has no attribute 'something_else'",
getattr, mock, 'something_else'
@@ -546,19 +512,20 @@ class MockTest(unittest.TestCase):
class Something(object):
x = 3
__something__ = None
- def y(self): pass
+ def y(self):
+ pass
def test_attributes(mock):
# should work
mock.x
mock.y
mock.__something__
- self.assertRaisesRegexp(
+ self.assertRaisesRegex(
AttributeError,
"Mock object has no attribute 'z'",
getattr, mock, 'z'
)
- self.assertRaisesRegexp(
+ self.assertRaisesRegex(
AttributeError,
"Mock object has no attribute '__foobar__'",
getattr, mock, '__foobar__'
@@ -580,16 +547,6 @@ class MockTest(unittest.TestCase):
real.assert_called_with(1, 2, fish=3)
- def test_wraps_prevents_automatic_creation_of_mocks(self):
- class Real(object):
- pass
-
- real = Real()
- mock = Mock(wraps=real)
-
- self.assertRaises(AttributeError, lambda: mock.new_attr())
-
-
def test_wraps_call_with_nondefault_return_value(self):
real = Mock()
@@ -616,110 +573,6 @@ class MockTest(unittest.TestCase):
self.assertEqual(result, Real.attribute.frog())
- def test_customize_wrapped_object_with_side_effect_iterable_with_default(self):
- class Real(object):
- def method(self):
- return sentinel.ORIGINAL_VALUE
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = [sentinel.VALUE1, DEFAULT]
-
- self.assertEqual(mock.method(), sentinel.VALUE1)
- self.assertEqual(mock.method(), sentinel.ORIGINAL_VALUE)
- self.assertRaises(StopIteration, mock.method)
-
-
- def test_customize_wrapped_object_with_side_effect_iterable(self):
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = [sentinel.VALUE1, sentinel.VALUE2]
-
- self.assertEqual(mock.method(), sentinel.VALUE1)
- self.assertEqual(mock.method(), sentinel.VALUE2)
- self.assertRaises(StopIteration, mock.method)
-
-
- def test_customize_wrapped_object_with_side_effect_exception(self):
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = RuntimeError
-
- self.assertRaises(RuntimeError, mock.method)
-
-
- def test_customize_wrapped_object_with_side_effect_function(self):
- class Real(object):
- def method(self): pass
- def side_effect():
- return sentinel.VALUE
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = side_effect
-
- self.assertEqual(mock.method(), sentinel.VALUE)
-
-
- def test_customize_wrapped_object_with_return_value(self):
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.return_value = sentinel.VALUE
-
- self.assertEqual(mock.method(), sentinel.VALUE)
-
-
- def test_customize_wrapped_object_with_return_value_and_side_effect(self):
- # side_effect should always take precedence over return_value.
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = [sentinel.VALUE1, sentinel.VALUE2]
- mock.method.return_value = sentinel.WRONG_VALUE
-
- self.assertEqual(mock.method(), sentinel.VALUE1)
- self.assertEqual(mock.method(), sentinel.VALUE2)
- self.assertRaises(StopIteration, mock.method)
-
-
- def test_customize_wrapped_object_with_return_value_and_side_effect2(self):
- # side_effect can return DEFAULT to default to return_value
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = lambda: DEFAULT
- mock.method.return_value = sentinel.VALUE
-
- self.assertEqual(mock.method(), sentinel.VALUE)
-
-
- def test_customize_wrapped_object_with_return_value_and_side_effect_default(self):
- class Real(object):
- def method(self): pass
-
- real = Real()
- mock = Mock(wraps=real)
- mock.method.side_effect = [sentinel.VALUE1, DEFAULT]
- mock.method.return_value = sentinel.RETURN
-
- self.assertEqual(mock.method(), sentinel.VALUE1)
- self.assertEqual(mock.method(), sentinel.RETURN)
- self.assertRaises(StopIteration, mock.method)
-
-
def test_exceptional_side_effect(self):
mock = Mock(side_effect=AttributeError)
self.assertRaises(AttributeError, mock)
@@ -738,13 +591,13 @@ class MockTest(unittest.TestCase):
def test_assert_called_with_message(self):
mock = Mock()
- self.assertRaisesRegexp(AssertionError, 'not called',
+ self.assertRaisesRegex(AssertionError, 'Not called',
mock.assert_called_with)
def test_assert_called_once_with_message(self):
mock = Mock(name='geoffrey')
- self.assertRaisesRegexp(AssertionError,
+ self.assertRaisesRegex(AssertionError,
r"Expected 'geoffrey' to be called once\.",
mock.assert_called_once_with)
@@ -787,30 +640,6 @@ class MockTest(unittest.TestCase):
self.assertIsInstance(mock, X)
- def test_spec_class_no_object_base(self):
- class X:
- pass
-
- mock = Mock(spec=X)
- self.assertIsInstance(mock, X)
-
- if not six.PY2:
- # This isn't true on Py2, we should fix if anyone complains:
- mock = Mock(spec=X())
- self.assertIsInstance(mock, X)
-
- self.assertIs(mock.__class__, X)
- self.assertEqual(Mock().__class__.__name__, 'Mock')
-
- mock = Mock(spec_set=X)
- self.assertIsInstance(mock, X)
-
- if not six.PY2:
- # This isn't true on Py2, we should fix if anyone complains:
- mock = Mock(spec_set=X())
- self.assertIsInstance(mock, X)
-
-
def test_setting_attribute_with_spec_set(self):
class X(object):
y = 3
@@ -953,15 +782,6 @@ class MockTest(unittest.TestCase):
patcher.stop()
- def test_dir_does_not_include_deleted_attributes(self):
- mock = Mock()
- mock.child.return_value = 1
-
- self.assertIn('child', dir(mock))
- del mock.child
- self.assertNotIn('child', dir(mock))
-
-
def test_configure_mock(self):
mock = Mock(foo='bar')
self.assertEqual(mock.foo, 'bar')
@@ -985,20 +805,25 @@ class MockTest(unittest.TestCase):
def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs):
# needed because assertRaisesRegex doesn't work easily with newlines
- with self.assertRaises(exception) as context:
+ try:
func(*args, **kwargs)
- msg = str(context.exception)
+ except:
+ instance = sys.exc_info()[1]
+ self.assertIsInstance(instance, exception)
+ else:
+ self.fail('Exception %r not raised' % (exception,))
+
+ msg = str(instance)
self.assertEqual(msg, message)
def test_assert_called_with_failure_message(self):
mock = NonCallableMock()
- actual = 'not called.'
expected = "mock(1, '2', 3, bar='foo')"
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nNot called'
self.assertRaisesWithMsg(
- AssertionError, message % (expected, actual),
+ AssertionError, message % (expected,),
mock.assert_called_with, 1, '2', 3, bar='foo'
)
@@ -1011,7 +836,7 @@ class MockTest(unittest.TestCase):
for meth in asserters:
actual = "foo(1, '2', 3, foo='foo')"
expected = "foo(1, '2', 3, bar='foo')"
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nActual call: %s'
self.assertRaisesWithMsg(
AssertionError, message % (expected, actual),
meth, 1, '2', 3, bar='foo'
@@ -1021,7 +846,7 @@ class MockTest(unittest.TestCase):
for meth in asserters:
actual = "foo(1, '2', 3, foo='foo')"
expected = "foo(bar='foo')"
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nActual call: %s'
self.assertRaisesWithMsg(
AssertionError, message % (expected, actual),
meth, bar='foo'
@@ -1031,7 +856,7 @@ class MockTest(unittest.TestCase):
for meth in asserters:
actual = "foo(1, '2', 3, foo='foo')"
expected = "foo(1, 2, 3)"
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nActual call: %s'
self.assertRaisesWithMsg(
AssertionError, message % (expected, actual),
meth, 1, 2, 3
@@ -1041,7 +866,7 @@ class MockTest(unittest.TestCase):
for meth in asserters:
actual = "foo(1, '2', 3, foo='foo')"
expected = "foo()"
- message = 'expected call not found.\nExpected: %s\nActual: %s'
+ message = 'Expected call: %s\nActual call: %s'
self.assertRaisesWithMsg(
AssertionError, message % (expected, actual), meth
)
@@ -1125,69 +950,6 @@ class MockTest(unittest.TestCase):
call().__int__().call_list())
- def test_child_mock_call_equal(self):
- m = Mock()
- result = m()
- result.wibble()
- # parent looks like this:
- self.assertEqual(m.mock_calls, [call(), call().wibble()])
- # but child should look like this:
- self.assertEqual(result.mock_calls, [call.wibble()])
-
-
- def test_mock_call_not_equal_leaf(self):
- m = Mock()
- m.foo().something()
- self.assertNotEqual(m.mock_calls[1], call.foo().different())
- self.assertEqual(m.mock_calls[0], call.foo())
-
-
- def test_mock_call_not_equal_non_leaf(self):
- m = Mock()
- m.foo().bar()
- self.assertNotEqual(m.mock_calls[1], call.baz().bar())
- self.assertNotEqual(m.mock_calls[0], call.baz())
-
-
- def test_mock_call_not_equal_non_leaf_params_different(self):
- m = Mock()
- m.foo(x=1).bar()
- # This isn't ideal, but there's no way to fix it without breaking backwards compatibility:
- self.assertEqual(m.mock_calls[1], call.foo(x=2).bar())
-
-
- def test_mock_call_not_equal_non_leaf_attr(self):
- m = Mock()
- m.foo.bar()
- self.assertNotEqual(m.mock_calls[0], call.baz.bar())
-
-
- def test_mock_call_not_equal_non_leaf_call_versus_attr(self):
- m = Mock()
- m.foo.bar()
- self.assertNotEqual(m.mock_calls[0], call.foo().bar())
-
-
- def test_mock_call_repr(self):
- m = Mock()
- m.foo().bar().baz.bob()
- self.assertEqual(repr(m.mock_calls[0]), 'call.foo()')
- self.assertEqual(repr(m.mock_calls[1]), 'call.foo().bar()')
- self.assertEqual(repr(m.mock_calls[2]), 'call.foo().bar().baz.bob()')
-
-
- def test_mock_call_repr_loop(self):
- m = Mock()
- m.foo = m
- repr(m.foo())
- self.assertRegexpMatches(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>")
-
-
- def test_mock_calls_contains(self):
- m = Mock()
- self.assertFalse([call()] in m.mock_calls)
-
-
def test_subclassing(self):
class Subclass(Mock):
pass
@@ -1246,8 +1008,9 @@ class MockTest(unittest.TestCase):
mock(2, b=4)
self.assertEqual(len(mock.call_args), 2)
- self.assertEqual(mock.call_args.args, (2,))
- self.assertEqual(mock.call_args.kwargs, dict(b=4))
+ args, kwargs = mock.call_args
+ self.assertEqual(args, (2,))
+ self.assertEqual(kwargs, dict(b=4))
expected_list = [((1,), dict(a=3)), ((2,), dict(b=4))]
for expected, call_args in zip(expected_list, mock.call_args_list):
@@ -1402,7 +1165,8 @@ class MockTest(unittest.TestCase):
def test_assert_has_calls_with_function_spec(self):
- def f(a, b, c, d=None): pass
+ def f(a, b, c, d=None):
+ pass
mock = Mock(spec=f)
@@ -1460,7 +1224,8 @@ class MockTest(unittest.TestCase):
def test_assert_any_call_with_function_spec(self):
- def f(a, b, c, d=None): pass
+ def f(a, b, c, d=None):
+ pass
mock = Mock(spec=f)
@@ -1480,7 +1245,8 @@ class MockTest(unittest.TestCase):
def test_mock_calls_create_autospec(self):
- def f(a, b): pass
+ def f(a, b):
+ pass
obj = Iter()
obj.f = f
@@ -1501,20 +1267,6 @@ class MockTest(unittest.TestCase):
m = mock.create_autospec(object(), name='sweet_func')
self.assertIn('sweet_func', repr(m))
- #Issue23078
- def test_create_autospec_classmethod_and_staticmethod(self):
- class TestClass:
- @classmethod
- def class_method(cls): pass
-
- @staticmethod
- def static_method(): pass
- for method in ('class_method', 'static_method'):
- mock_method = mock.create_autospec(getattr(TestClass, method))
- mock_method()
- mock_method.assert_called_once_with()
- self.assertRaises(TypeError, mock_method, 'extra_arg')
-
#Issue21238
def test_mock_unsafe(self):
m = Mock()
@@ -1534,13 +1286,6 @@ class MockTest(unittest.TestCase):
with self.assertRaises(AssertionError):
m.hello.assert_not_called()
- def test_assert_not_called_message(self):
- m = Mock()
- m(1, 2)
- self.assertRaisesRegexp(AssertionError,
- re.escape("Calls: [call(1, 2)]"),
- m.assert_not_called)
-
def test_assert_called(self):
m = Mock()
with self.assertRaises(AssertionError):
@@ -1562,20 +1307,6 @@ class MockTest(unittest.TestCase):
with self.assertRaises(AssertionError):
m.hello.assert_called_once()
- def test_assert_called_once_message(self):
- m = Mock()
- m(1, 2)
- m(3)
- self.assertRaisesRegexp(AssertionError,
- re.escape("Calls: [call(1, 2), call(3)]"),
- m.assert_called_once)
-
- def test_assert_called_once_message_not_called(self):
- m = Mock()
- with self.assertRaises(AssertionError) as e:
- m.assert_called_once()
- self.assertNotIn("Calls:", str(e.exception))
-
#Issue21256 printout of keyword args should be in deterministic order
def test_sorted_call_signature(self):
m = Mock()
@@ -1593,24 +1324,6 @@ class MockTest(unittest.TestCase):
self.assertEqual(m.method_calls[0], c)
self.assertEqual(m.method_calls[1], i)
- def test_reset_return_sideeffect(self):
- m = Mock(return_value=10, side_effect=[2,3])
- m.reset_mock(return_value=True, side_effect=True)
- self.assertIsInstance(m.return_value, Mock)
- self.assertEqual(m.side_effect, None)
-
- def test_reset_return(self):
- m = Mock(return_value=10, side_effect=[2,3])
- m.reset_mock(return_value=True)
- self.assertIsInstance(m.return_value, Mock)
- self.assertNotEqual(m.side_effect, None)
-
- def test_reset_sideeffect(self):
- m = Mock(return_value=10, side_effect=[2,3])
- m.reset_mock(side_effect=True)
- self.assertEqual(m.return_value, 10)
- self.assertEqual(m.side_effect, None)
-
def test_mock_add_spec(self):
class _One(object):
one = 1
@@ -1755,16 +1468,6 @@ class MockTest(unittest.TestCase):
f2_data = f2.read()
self.assertEqual(f1_data, f2_data)
- def test_mock_open_dunder_iter_issue(self):
- # Test dunder_iter method generates the expected result and
- # consumes the iterator.
- mocked_open = mock.mock_open(read_data='Remarkable\nNorwegian Blue')
- f1 = mocked_open('a-name')
- lines = [line for line in f1]
- self.assertEqual(lines[0], 'Remarkable\n')
- self.assertEqual(lines[1], 'Norwegian Blue')
- self.assertEqual(list(f1), [])
-
def test_mock_open_write(self):
# Test exception in file writing write()
mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV'))
@@ -1783,21 +1486,7 @@ class MockTest(unittest.TestCase):
second = mopen().readline()
self.assertEqual('abc', first)
self.assertEqual('abc', second)
-
-
- def test_mock_open_after_eof(self):
- # read, readline and readlines should work after end of file.
- _open = mock.mock_open(read_data='foo')
- h = _open('bar')
- h.read()
- self.assertEqual('', h.read())
- self.assertEqual('', h.read())
- self.assertEqual('', h.readline())
- self.assertEqual('', h.readline())
- self.assertEqual([], h.readlines())
- self.assertEqual([], h.readlines())
-
-
+
def test_mock_parents(self):
for Klass in Mock, MagicMock:
m = Klass()
@@ -1873,43 +1562,6 @@ class MockTest(unittest.TestCase):
self.assertRaises(AttributeError, getattr, mock, 'f')
- def test_mock_does_not_raise_on_repeated_attribute_deletion(self):
- # bpo-20239: Assigning and deleting twice an attribute raises.
- for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
- NonCallableMock()):
- mock.foo = 3
- self.assertTrue(hasattr(mock, 'foo'))
- self.assertEqual(mock.foo, 3)
-
- del mock.foo
- self.assertFalse(hasattr(mock, 'foo'))
-
- mock.foo = 4
- self.assertTrue(hasattr(mock, 'foo'))
- self.assertEqual(mock.foo, 4)
-
- del mock.foo
- self.assertFalse(hasattr(mock, 'foo'))
-
-
- def test_mock_raises_when_deleting_nonexistent_attribute(self):
- for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
- NonCallableMock()):
- del mock.foo
- with self.assertRaises(AttributeError):
- del mock.foo
-
-
- def test_reset_mock_does_not_raise_on_attr_deletion(self):
- # bpo-31177: reset_mock should not raise AttributeError when attributes
- # were deleted in a mock instance
- mock = Mock()
- mock.child = True
- del mock.child
- mock.reset_mock()
- self.assertFalse(hasattr(mock, 'child'))
-
-
def test_class_assignable(self):
for mock in Mock(), MagicMock():
self.assertNotIsInstance(mock, int)
@@ -1918,59 +1570,21 @@ class MockTest(unittest.TestCase):
self.assertIsInstance(mock, int)
mock.foo
- def test_name_attribute_of_call(self):
- # bpo-35357: _Call should not disclose any attributes whose names
- # may clash with popular ones (such as ".name")
- self.assertIsNotNone(call.name)
- self.assertEqual(type(call.name), _Call)
- self.assertEqual(type(call.name().name), _Call)
- def test_parent_attribute_of_call(self):
- # bpo-35357: _Call should not disclose any attributes whose names
- # may clash with popular ones (such as ".parent")
- self.assertIsNotNone(call.parent)
- self.assertEqual(type(call.parent), _Call)
- self.assertEqual(type(call.parent().parent), _Call)
-
- def test_parent_propagation_with_create_autospec(self):
- def foo(a, b): pass
-
- mock = Mock()
- mock.child = create_autospec(foo)
- mock.child(1, 2)
- self.assertRaises(TypeError, mock.child, 1)
- self.assertEqual(mock.mock_calls, [call.child(1, 2)])
-
- def test_isinstance_under_settrace(self):
- # bpo-36593 : __class__ is not set for a class that has __class__
- # property defined when it's used with sys.settrace(trace) set.
- # Delete the module to force reimport with tracing function set
- # restore the old reference later since there are other tests that are
- # dependent on unittest.mock.patch. In testpatch.PatchTest
- # test_patch_dict_test_prefix and test_patch_test_prefix not restoring
- # causes the objects patched to go out of sync
- old_patch = mock.patch
- # Directly using __setattr__ on unittest.mock causes current imported
- # reference to be updated. Use a lambda so that during cleanup the
- # re-imported new reference is updated.
- self.addCleanup(lambda patch: setattr(mock, 'patch', patch),
- old_patch)
- with patch.dict('sys.modules'):
- del sys.modules['mock.mock']
- # This trace will stop coverage being measured ;-)
- def trace(frame, event, arg): # pragma: no cover
- return trace
- self.addCleanup(sys.settrace, sys.gettrace())
- sys.settrace(trace)
- from mock.mock import (
- Mock, MagicMock, NonCallableMock, NonCallableMagicMock
- )
- mocks = [
- Mock, MagicMock, NonCallableMock, NonCallableMagicMock
- ]
- for mock_ in mocks:
- obj = mock_(spec=Something)
- self.assertIsInstance(obj, Something)
+ @unittest.expectedFailure
+ def test_pickle(self):
+ for Klass in (MagicMock, Mock, Subclass, NonCallableMagicMock):
+ mock = Klass(name='foo', attribute=3)
+ mock.foo(1, 2, 3)
+ data = pickle.dumps(mock)
+ new = pickle.loads(data)
+
+ new.foo.assert_called_once_with(1, 2, 3)
+ self.assertFalse(new.called)
+ self.assertTrue(is_instance(new, Klass))
+ self.assertIsInstance(new, Thing)
+ self.assertIn('name="foo"', repr(new))
+ self.assertEqual(new.attribute, 3)
if __name__ == '__main__':
diff --git a/mock/tests/testpatch.py b/mock/tests/testpatch.py
index bbd6d26..f31ccef 100644
--- a/mock/tests/testpatch.py
+++ b/mock/tests/testpatch.py
@@ -6,14 +6,14 @@ import os
import sys
import six
-import unittest
+import unittest2 as unittest
from mock.tests import support
-from mock.tests.support import SomeClass, is_instance, uncache
+from mock.tests.support import SomeClass, is_instance
from mock import (
NonCallableMock, CallableMixin, patch, sentinel,
- MagicMock, Mock, NonCallableMagicMock,
+ MagicMock, Mock, NonCallableMagicMock, patch,
DEFAULT, call
)
from mock.mock import _patch, _get_target
@@ -47,24 +47,23 @@ something_else = sentinel.SomethingElse
class Foo(object):
- def __init__(self, a): pass
- def f(self, a): pass
- def g(self): pass
+ def __init__(self, a):
+ pass
+ def f(self, a):
+ pass
+ def g(self):
+ pass
foo = 'bar'
- @staticmethod
- def static_method(): pass
-
- @classmethod
- def class_method(cls): pass
-
class Bar(object):
- def a(self): pass
+ def a(self):
+ pass
foo_name = '%s.Foo' % __name__
-def function(a, b=Foo): pass
+def function(a, b=Foo):
+ pass
class Container(object):
@@ -367,19 +366,31 @@ class PatchTest(unittest.TestCase):
def test_patch_wont_create_by_default(self):
- with self.assertRaises(AttributeError):
+ try:
@patch('%s.frooble' % builtin_string, sentinel.Frooble)
- def test(): pass
+ def test():
+ self.assertEqual(frooble, sentinel.Frooble)
test()
+ except AttributeError:
+ pass
+ else:
+ self.fail('Patching non existent attributes should fail')
+
self.assertRaises(NameError, lambda: frooble)
def test_patchobject_wont_create_by_default(self):
- with self.assertRaises(AttributeError):
+ try:
@patch.object(SomeClass, 'ord', sentinel.Frooble)
- def test(): pass
+ def test():
+ self.fail('Patching non existent attributes should fail')
+
test()
+ except AttributeError:
+ pass
+ else:
+ self.fail('Patching non existent attributes should fail')
self.assertFalse(hasattr(SomeClass, 'ord'))
@@ -469,9 +480,6 @@ class PatchTest(unittest.TestCase):
attribute = sentinel.Original
class Foo(object):
-
- test_class_attr = 'whatever'
-
def test_method(other_self, mock_something):
self.assertEqual(PTModule.something, mock_something,
"unpatched")
@@ -630,7 +638,8 @@ class PatchTest(unittest.TestCase):
@patch('%s.SomeClass' % __name__, object(), autospec=True)
@patch.object(SomeClass, object())
@patch.dict(foo)
- def some_name(): pass
+ def some_name():
+ pass
self.assertEqual(some_name.__name__, 'some_name')
@@ -641,9 +650,12 @@ class PatchTest(unittest.TestCase):
@patch.dict(foo, {'a': 'b'})
def test():
raise NameError('Konrad')
-
- with self.assertRaises(NameError):
+ try:
test()
+ except NameError:
+ pass
+ else:
+ self.fail('NameError not raised by test')
self.assertEqual(foo, {})
@@ -656,37 +668,57 @@ class PatchTest(unittest.TestCase):
test()
- def test_patch_dict_with_unicode(self):
- @patch.dict(u'os.environ', {'konrad_delong': 'some value'})
- def test():
- self.assertIn('konrad_delong', os.environ)
+ @unittest.expectedFailure
+ def test_patch_descriptor(self):
+ # would be some effort to fix this - we could special case the
+ # builtin descriptors: classmethod, property, staticmethod
+ class Nothing(object):
+ foo = None
- test()
+ class Something(object):
+ foo = {}
+ @patch.object(Nothing, 'foo', 2)
+ @classmethod
+ def klass(cls):
+ self.assertIs(cls, Something)
- def test_patch_dict_decorator_resolution(self):
- # bpo-35512: Ensure that patch with a string target resolves to
- # the new dictionary during function call
- original = support.target.copy()
- @patch.dict('mock.tests.support.target', {'bar': 'BAR'})
- def test():
- self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'})
- try:
- support.target = {'foo': 'BAZ'}
- test()
- self.assertEqual(support.target, {'foo': 'BAZ'})
- finally:
- support.target = original
+ @patch.object(Nothing, 'foo', 2)
+ @staticmethod
+ def static(arg):
+ return arg
+
+ @patch.dict(foo)
+ @classmethod
+ def klass_dict(cls):
+ self.assertIs(cls, Something)
+
+ @patch.dict(foo)
+ @staticmethod
+ def static_dict(arg):
+ return arg
+
+ # these will raise exceptions if patching descriptors is broken
+ self.assertEqual(Something.static('f00'), 'f00')
+ Something.klass()
+ self.assertEqual(Something.static_dict('f00'), 'f00')
+ Something.klass_dict()
+
+ something = Something()
+ self.assertEqual(something.static('f00'), 'f00')
+ something.klass()
+ self.assertEqual(something.static_dict('f00'), 'f00')
+ something.klass_dict()
def test_patch_spec_set(self):
- @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True)
+ @patch('%s.SomeClass' % __name__, spec_set=SomeClass)
def test(MockClass):
MockClass.z = 'foo'
self.assertRaises(AttributeError, test)
- @patch.object(support, 'SomeClass', spec=SomeClass, spec_set=True)
+ @patch.object(support, 'SomeClass', spec_set=SomeClass)
def test(MockClass):
MockClass.z = 'foo'
@@ -727,18 +759,10 @@ class PatchTest(unittest.TestCase):
def test_stop_without_start(self):
- # bpo-36366: calling stop without start will return None.
patcher = patch(foo_name, 'bar', 3)
- self.assertIsNone(patcher.stop())
-
- def test_stop_idempotent(self):
- # bpo-36366: calling stop on an already stopped patch will return None.
- patcher = patch(foo_name, 'bar', 3)
-
- patcher.start()
- patcher.stop()
- self.assertIsNone(patcher.stop())
+ # calling stop without start used to produce a very obscure error
+ self.assertRaises(RuntimeError, patcher.stop)
def test_patchobject_start_stop(self):
@@ -878,13 +902,17 @@ class PatchTest(unittest.TestCase):
def test_autospec(self):
class Boo(object):
- def __init__(self, a): pass
- def f(self, a): pass
- def g(self): pass
+ def __init__(self, a):
+ pass
+ def f(self, a):
+ pass
+ def g(self):
+ pass
foo = 'bar'
class Bar(object):
- def a(self): pass
+ def a(self):
+ pass
def _test(mock):
mock(1)
@@ -946,14 +974,8 @@ class PatchTest(unittest.TestCase):
def test_autospec_function(self):
@patch('%s.function' % __name__, autospec=True)
def test(mock):
- function.assert_not_called()
- self.assertRaises(AssertionError, function.assert_called)
- self.assertRaises(AssertionError, function.assert_called_once)
function(1)
- self.assertRaises(AssertionError, function.assert_not_called)
function.assert_called_with(1)
- function.assert_called()
- function.assert_called_once()
function(2, 3)
function.assert_called_with(2, 3)
@@ -974,18 +996,6 @@ class PatchTest(unittest.TestCase):
self.assertEqual(result, 3)
- def test_autospec_staticmethod(self):
- with patch('%s.Foo.static_method' % __name__, autospec=True) as method:
- Foo.static_method()
- method.assert_called_once_with()
-
-
- def test_autospec_classmethod(self):
- with patch('%s.Foo.class_method' % __name__, autospec=True) as method:
- Foo.class_method()
- method.assert_called_once_with()
-
-
def test_autospec_with_new(self):
patcher = patch('%s.function' % __name__, new=3, autospec=True)
self.assertRaises(TypeError, patcher.start)
@@ -1255,6 +1265,7 @@ class PatchTest(unittest.TestCase):
def test_patch_multiple_create_mocks_different_order(self):
+ # bug revealed by Jython!
original_f = Foo.f
original_g = Foo.g
@@ -1431,17 +1442,20 @@ class PatchTest(unittest.TestCase):
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'missing', 1)
@patch.object(Foo, 'f', 1)
- def thing1(): pass
+ def thing1():
+ pass
@patch.object(Foo, 'missing', 1)
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1)
- def thing2(): pass
+ def thing2():
+ pass
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1)
@patch.object(Foo, 'missing', 1)
- def thing3(): pass
+ def thing3():
+ pass
for func in thing1, thing2, thing3:
self.assertRaises(AttributeError, func)
@@ -1460,17 +1474,20 @@ class PatchTest(unittest.TestCase):
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'foo', new_callable=crasher)
@patch.object(Foo, 'f', 1)
- def thing1(): pass
+ def thing1():
+ pass
@patch.object(Foo, 'foo', new_callable=crasher)
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1)
- def thing2(): pass
+ def thing2():
+ pass
@patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1)
@patch.object(Foo, 'foo', new_callable=crasher)
- def thing3(): pass
+ def thing3():
+ pass
for func in thing1, thing2, thing3:
self.assertRaises(NameError, func)
@@ -1496,7 +1513,8 @@ class PatchTest(unittest.TestCase):
patcher.additional_patchers = additionals
@patcher
- def func(): pass
+ def func():
+ pass
self.assertRaises(AttributeError, func)
self.assertEqual(Foo.f, original_f)
@@ -1524,7 +1542,8 @@ class PatchTest(unittest.TestCase):
patcher.additional_patchers = additionals
@patcher
- def func(): pass
+ def func():
+ pass
self.assertRaises(NameError, func)
self.assertEqual(Foo.f, original_f)
@@ -1644,20 +1663,21 @@ class PatchTest(unittest.TestCase):
def test_patch_imports_lazily(self):
+ sys.modules.pop('squizz', None)
+
p1 = patch('squizz.squozz')
self.assertRaises(ImportError, p1.start)
- with uncache('squizz'):
- squizz = Mock()
- sys.modules['squizz'] = squizz
-
- squizz.squozz = 6
- p1 = patch('squizz.squozz')
- squizz.squozz = 3
- p1.start()
- p1.stop()
+ squizz = Mock()
+ squizz.squozz = 6
+ sys.modules['squizz'] = squizz
+ p1 = patch('squizz.squozz')
+ squizz.squozz = 3
+ p1.start()
+ p1.stop()
self.assertEqual(squizz.squozz, 3)
+
def test_patch_propogrates_exc_on_exit(self):
class holder:
exc_info = None, None, None
@@ -1679,12 +1699,7 @@ class PatchTest(unittest.TestCase):
def test(mock):
raise RuntimeError
- with uncache('squizz'):
- squizz = Mock()
- sys.modules['squizz'] = squizz
-
- self.assertRaises(RuntimeError, test)
-
+ self.assertRaises(RuntimeError, test)
self.assertIs(holder.exc_info[0], RuntimeError)
self.assertIsNotNone(holder.exc_info[1],
'exception value not propgated')
@@ -1864,35 +1879,5 @@ class PatchTest(unittest.TestCase):
self.assertEqual(foo(), 1)
self.assertEqual(foo(), 0)
-
- def test_dotted_but_module_not_loaded(self):
- # This exercises the AttributeError branch of _dot_lookup.
- # make sure it's there
- import mock.tests.support
- # now make sure it's not:
- with patch.dict('sys.modules'):
- del sys.modules['mock.tests.support']
- del sys.modules['mock.tests']
- del sys.modules['mock.mock']
- del sys.modules['mock']
- # now make sure we can patch based on a dotted path:
- @patch('mock.tests.support.X')
- def test(mock):
- pass
- test()
-
-
- def test_invalid_target(self):
- with self.assertRaises(TypeError):
- patch('')
-
-
- def test_cant_set_kwargs_when_passing_a_mock(self):
- @patch('mock.tests.support.X', new=object(), x=1)
- def test(): pass
- with self.assertRaises(TypeError):
- test()
-
-
if __name__ == '__main__':
unittest.main()
diff --git a/mock/tests/testsealable.py b/mock/tests/testsealable.py
deleted file mode 100644
index 63a8541..0000000
--- a/mock/tests/testsealable.py
+++ /dev/null
@@ -1,176 +0,0 @@
-import unittest
-import mock
-
-
-class SampleObject:
-
- def method_sample1(self): pass
-
- def method_sample2(self): pass
-
-
-class TestSealable(unittest.TestCase):
-
- def test_attributes_return_more_mocks_by_default(self):
- m = mock.Mock()
-
- self.assertIsInstance(m.test, mock.Mock)
- self.assertIsInstance(m.test(), mock.Mock)
- self.assertIsInstance(m.test().test2(), mock.Mock)
-
- def test_new_attributes_cannot_be_accessed_on_seal(self):
- m = mock.Mock()
-
- mock.seal(m)
- with self.assertRaises(AttributeError):
- m.test
- with self.assertRaises(AttributeError):
- m()
-
- def test_new_attributes_cannot_be_set_on_seal(self):
- m = mock.Mock()
-
- mock.seal(m)
- with self.assertRaises(AttributeError):
- m.test = 1
-
- def test_existing_attributes_can_be_set_on_seal(self):
- m = mock.Mock()
- m.test.test2 = 1
-
- mock.seal(m)
- m.test.test2 = 2
- self.assertEqual(m.test.test2, 2)
-
- def test_new_attributes_cannot_be_set_on_child_of_seal(self):
- m = mock.Mock()
- m.test.test2 = 1
-
- mock.seal(m)
- with self.assertRaises(AttributeError):
- m.test.test3 = 1
-
- def test_existing_attributes_allowed_after_seal(self):
- m = mock.Mock()
-
- m.test.return_value = 3
-
- mock.seal(m)
- self.assertEqual(m.test(), 3)
-
- def test_initialized_attributes_allowed_after_seal(self):
- m = mock.Mock(test_value=1)
-
- mock.seal(m)
- self.assertEqual(m.test_value, 1)
-
- def test_call_on_sealed_mock_fails(self):
- m = mock.Mock()
-
- mock.seal(m)
- with self.assertRaises(AttributeError):
- m()
-
- def test_call_on_defined_sealed_mock_succeeds(self):
- m = mock.Mock(return_value=5)
-
- mock.seal(m)
- self.assertEqual(m(), 5)
-
- def test_seals_recurse_on_added_attributes(self):
- m = mock.Mock()
-
- m.test1.test2().test3 = 4
-
- mock.seal(m)
- self.assertEqual(m.test1.test2().test3, 4)
- with self.assertRaises(AttributeError):
- m.test1.test2().test4
- with self.assertRaises(AttributeError):
- m.test1.test3
-
- def test_seals_recurse_on_magic_methods(self):
- m = mock.MagicMock()
-
- m.test1.test2["a"].test3 = 4
- m.test1.test3[2:5].test3 = 4
-
- mock.seal(m)
- self.assertEqual(m.test1.test2["a"].test3, 4)
- self.assertEqual(m.test1.test2[2:5].test3, 4)
- with self.assertRaises(AttributeError):
- m.test1.test2["a"].test4
- with self.assertRaises(AttributeError):
- m.test1.test3[2:5].test4
-
- def test_seals_dont_recurse_on_manual_attributes(self):
- m = mock.Mock(name="root_mock")
-
- m.test1.test2 = mock.Mock(name="not_sealed")
- m.test1.test2.test3 = 4
-
- mock.seal(m)
- self.assertEqual(m.test1.test2.test3, 4)
- m.test1.test2.test4 # Does not raise
- m.test1.test2.test4 = 1 # Does not raise
-
- def test_integration_with_spec_att_definition(self):
- """You are not restricted when using mock with spec"""
- m = mock.Mock(SampleObject)
-
- m.attr_sample1 = 1
- m.attr_sample3 = 3
-
- mock.seal(m)
- self.assertEqual(m.attr_sample1, 1)
- self.assertEqual(m.attr_sample3, 3)
- with self.assertRaises(AttributeError):
- m.attr_sample2
-
- def test_integration_with_spec_method_definition(self):
- """You need to defin the methods, even if they are in the spec"""
- m = mock.Mock(SampleObject)
-
- m.method_sample1.return_value = 1
-
- mock.seal(m)
- self.assertEqual(m.method_sample1(), 1)
- with self.assertRaises(AttributeError):
- m.method_sample2()
-
- def test_integration_with_spec_method_definition_respects_spec(self):
- """You cannot define methods out of the spec"""
- m = mock.Mock(SampleObject)
-
- with self.assertRaises(AttributeError):
- m.method_sample3.return_value = 3
-
- def test_sealed_exception_has_attribute_name(self):
- m = mock.Mock()
-
- mock.seal(m)
- with self.assertRaises(AttributeError) as cm:
- m.SECRETE_name
- self.assertIn("SECRETE_name", str(cm.exception))
-
- def test_attribute_chain_is_maintained(self):
- m = mock.Mock(name="mock_name")
- m.test1.test2.test3.test4
-
- mock.seal(m)
- with self.assertRaises(AttributeError) as cm:
- m.test1.test2.test3.test4.boom
- self.assertIn("mock_name.test1.test2.test3.test4.boom", str(cm.exception))
-
- def test_call_chain_is_maintained(self):
- m = mock.Mock()
- m.test1().test2.test3().test4
-
- mock.seal(m)
- with self.assertRaises(AttributeError) as cm:
- m.test1().test2.test3().test4()
- self.assertIn("mock.test1().test2.test3().test4", str(cm.exception))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/mock/tests/testsentinel.py b/mock/tests/testsentinel.py
index 1411445..69b2042 100644
--- a/mock/tests/testsentinel.py
+++ b/mock/tests/testsentinel.py
@@ -2,9 +2,8 @@
# E-mail: fuzzyman AT voidspace DOT org DOT uk
# http://www.voidspace.org.uk/python/mock/
-import unittest
-import copy
-import pickle
+import unittest2 as unittest
+
from mock import sentinel, DEFAULT
@@ -29,16 +28,6 @@ class SentinelTest(unittest.TestCase):
# If this doesn't raise an AttributeError then help(mock) is broken
self.assertRaises(AttributeError, lambda: sentinel.__bases__)
- def testPickle(self):
- for proto in range(pickle.HIGHEST_PROTOCOL+1):
- pickled = pickle.dumps(sentinel.whatever, proto)
- unpickled = pickle.loads(pickled)
- self.assertIs(unpickled, sentinel.whatever)
-
- def testCopy(self):
- self.assertIs(copy.copy(sentinel.whatever), sentinel.whatever)
- self.assertIs(copy.deepcopy(sentinel.whatever), sentinel.whatever)
-
if __name__ == '__main__':
unittest.main()
diff --git a/mock/tests/testsupport.py b/mock/tests/testsupport.py
deleted file mode 100644
index 4882572..0000000
--- a/mock/tests/testsupport.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Tests to make sure helpers we backport are actually working!
-from unittest import TestCase
-
-from .support import uncache
-
-
-class TestUncache(TestCase):
-
- def test_cant_uncache_sys(self):
- with self.assertRaises(ValueError):
- with uncache('sys'): pass
-
- def test_uncache_non_existent(self):
- with uncache('mock.tests.support.bad'): pass
diff --git a/mock/tests/testwith.py b/mock/tests/testwith.py
index 587fde9..aa7812b 100644
--- a/mock/tests/testwith.py
+++ b/mock/tests/testwith.py
@@ -4,7 +4,7 @@
from warnings import catch_warnings
-import unittest
+import unittest2 as unittest
from mock.tests.support import is_instance
from mock import MagicMock, Mock, patch, sentinel, mock_open, call
@@ -14,8 +14,6 @@ something = sentinel.Something
something_else = sentinel.SomethingElse
-class SampleException(Exception): pass
-
class WithTest(unittest.TestCase):
@@ -26,10 +24,14 @@ class WithTest(unittest.TestCase):
def test_with_statement_exception(self):
- with self.assertRaises(SampleException):
+ try:
with patch('%s.something' % __name__, sentinel.Something2):
self.assertEqual(something, sentinel.Something2, "unpatched")
- raise SampleException()
+ raise Exception('pow')
+ except Exception:
+ pass
+ else:
+ self.fail("patch swallowed exception")
self.assertEqual(something, sentinel.Something)
@@ -129,19 +131,6 @@ class WithTest(unittest.TestCase):
self.assertEqual(foo, {})
- def test_double_patch_instance_method(self):
- class C:
- def f(self): pass
-
- c = C()
-
- with patch.object(c, 'f', autospec=True) as patch1:
- with patch.object(c, 'f', autospec=True) as patch2:
- c.f()
- self.assertEqual(patch2.call_count, 1)
- self.assertEqual(patch1.call_count, 0)
- c.f()
- self.assertEqual(patch1.call_count, 1)
class TestMockOpen(unittest.TestCase):
@@ -204,7 +193,6 @@ class TestMockOpen(unittest.TestCase):
def test_readline_data(self):
# Check that readline will return all the lines from the fake file
- # And that once fully consumed, readline will return an empty string.
mock = mock_open(read_data='foo\nbar\nbaz\n')
with patch('%s.open' % __name__, mock, create=True):
h = open('bar')
@@ -214,7 +202,6 @@ class TestMockOpen(unittest.TestCase):
self.assertEqual(line1, 'foo\n')
self.assertEqual(line2, 'bar\n')
self.assertEqual(line3, 'baz\n')
- self.assertEqual(h.readline(), '')
# Check that we properly emulate a file that doesn't end in a newline
mock = mock_open(read_data='foo')
@@ -222,19 +209,6 @@ class TestMockOpen(unittest.TestCase):
h = open('bar')
result = h.readline()
self.assertEqual(result, 'foo')
- self.assertEqual(h.readline(), '')
-
-
- def test_dunder_iter_data(self):
- # Check that dunder_iter will return all the lines from the fake file.
- mock = mock_open(read_data='foo\nbar\nbaz\n')
- with patch('%s.open' % __name__, mock, create=True):
- h = open('bar')
- lines = [l for l in h]
- self.assertEqual(lines[0], 'foo\n')
- self.assertEqual(lines[1], 'bar\n')
- self.assertEqual(lines[2], 'baz\n')
- self.assertEqual(h.readline(), '')
def test_readlines_data(self):
@@ -288,12 +262,7 @@ class TestMockOpen(unittest.TestCase):
# for mocks returned by mock_open
some_data = 'foo\nbar\nbaz'
mock = mock_open(read_data=some_data)
- self.assertEqual(mock().read(10), some_data[:10])
- self.assertEqual(mock().read(10), some_data[:10])
-
- f = mock()
- self.assertEqual(f.read(10), some_data[:10])
- self.assertEqual(f.read(10), some_data[10:])
+ self.assertEqual(mock().read(10), some_data)
def test_interleaved_reads(self):
diff --git a/release.py b/release.py
deleted file mode 100644
index 2556d50..0000000
--- a/release.py
+++ /dev/null
@@ -1,92 +0,0 @@
-import re
-from glob import glob
-from os.path import join
-from subprocess import call
-
-import blurb as blurb_module
-from argparse import ArgumentParser
-from mock import version_info
-
-VERSION_TYPES = ['major', 'minor', 'bugfix']
-
-
-def incremented_version(version_info, type_):
- type_index = VERSION_TYPES.index(type_)
- version_info = tuple(e+(1 if i==type_index else 0)
- for i, e in enumerate(version_info))
- return '.'.join(str(p) for p in version_info)
-
-
-def text_from_news():
- # hack:
- blurb_module.sections.append('NEWS.d')
-
- blurbs = blurb_module.Blurbs()
- for path in glob(join('NEWS.d', '*')):
- blurbs.load_next(path)
-
- text = []
- for metadata, body in blurbs:
- bpo = metadata['bpo']
- body = f"- Issue #{bpo}: " + body
- text.append(blurb_module.textwrap_body(body, subsequent_indent=' '))
-
- return '\n'.join(text)
-
-
-def news_to_changelog(version):
- with open('CHANGELOG.rst') as source:
- current_changelog = source.read()
-
- text = [version]
- text.append('-'*len(version))
- text.append('')
- text.append(text_from_news())
- text.append(current_changelog)
-
- new_changelog = '\n'.join(text)
- with open('CHANGELOG.rst', 'w') as target:
- target.write(new_changelog)
-
-
-def update_version(new_version):
- path = join('mock', 'mock.py')
- with open(path) as source:
- text = source.read()
-
- text = re.sub("(__version__ = ')[^']+(')",
- r"\g<1>"+new_version+r"\2",
- text)
-
- with open(path, 'w') as target:
- target.write(text)
-
-
-def git(command):
- return call('git '+command, shell=True)
-
-
-def git_commit(new_version):
- git('rm NEWS.d/*')
- git('add CHANGELOG.rst')
- git('add mock/mock.py')
- git(f'commit -m "Preparing for {new_version} release."')
-
-
-def parse_args():
- parser = ArgumentParser()
- parser.add_argument('type', choices=VERSION_TYPES)
- return parser.parse_args()
-
-
-def main():
- args = parse_args()
- new_version = incremented_version(version_info, args.type)
- news_to_changelog(new_version)
- update_version(new_version)
- git_commit(new_version)
- print(f'{new_version} ready to push, please check the HEAD commit first!')
-
-
-if __name__ == '__main__':
- main()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..31bbe5d
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+funcsigs>=1;python_version<"3.3"
+# For runtime needs this is correct. For setup_requires needs, 1.2.0 is needed
+# but setuptools can't cope with conflicts in setup_requires, so thats
+# unversioned.
+pbr>=0.11
+six>=1.9
diff --git a/setup.cfg b/setup.cfg
index 7283b79..25c280b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,12 +1,11 @@
[metadata]
name = mock
summary = Rolling backport of unittest.mock for all Pythons
-home-page = http://mock.readthedocs.org/en/latest/
+home-page = https://github.com/testing-cabal/mock
description-file = README.rst
author = Testing Cabal
author-email = testing-in-python@lists.idyll.org
-license = OSI Approved :: BSD License
-classifier =
+classifier =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
@@ -16,11 +15,12 @@ classifier =
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
Programming Language :: Python :: Implementation :: CPython
+ Programming Language :: Python :: Implementation :: Jython
Programming Language :: Python :: Implementation :: PyPy
Topic :: Software Development :: Libraries
Topic :: Software Development :: Libraries :: Python Modules
@@ -28,28 +28,14 @@ classifier =
keyword =
testing, test, mock, mocking, unittest, patching, stubs, fakes, doubles
-[options]
-install_requires =
- six
- funcsigs>=1;python_version<"3.3"
-python_requires=>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
-packages = mock
-
-[options.extras_require]
+[extras]
+test =
+ unittest2>=1.1.0
docs =
sphinx
-test =
- pytest
- pytest-cov
-build =
- twine
- wheel
- blurb
+
+[files]
+packages = mock
[bdist_wheel]
universal = 1
-
-[tool:pytest]
-python_files=test*.py
-filterwarnings =
- ignore::DeprecationWarning
diff --git a/setup.py b/setup.py
index d47345f..5f727ae 100755
--- a/setup.py
+++ b/setup.py
@@ -1,10 +1,6 @@
-import re
-from os.path import join
-
+#!/usr/bin/env python
import setuptools
setuptools.setup(
- version=re.search("__version__ = '([^']+)'",
- open(join('mock', 'mock.py')).read()).group(1),
- long_description=open('README.rst').read(),
-)
+ setup_requires=['pbr>=1.3', 'setuptools>=17.1'],
+ pbr=True)
diff --git a/tools/applypatch-transform b/tools/applypatch-transform
new file mode 100755
index 0000000..52fcd93
--- /dev/null
+++ b/tools/applypatch-transform
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# An example hook script to transform a patch taken from an email
+# by git am.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit. The hook is
+# allowed to edit the patch file.
+#
+# To enable this hook, rename this file to "applypatch-transform".
+#
+# This example changes the path of Lib/unittest/mock.py to mock.py
+# Lib/unittest/tests/testmock to tests and Misc/NEWS to NEWS, and
+# finally skips any patches that did not alter mock.py or its tests.
+
+set -eux
+
+patch_path=$1
+
+# Pull out mock.py
+filterdiff --clean --strip 3 --addprefix=a/mock/ -i 'a/Lib/unittest/mock.py' -i 'b/Lib/unittest/mock.py' $patch_path > $patch_path.mock
+# And the tests
+filterdiff --clean --strip 5 --addprefix=a/mock/tests/ -i 'a/Lib/unittest/test/testmock/*.py' -i 'b/Lib/unittest/test/testmock/*.py' $patch_path > $patch_path.tests
+# Lastly we want to pick up any NEWS entries.
+filterdiff --strip 2 --addprefix=a/ -i a/Misc/NEWS -i b/Misc/NEWS $patch_path > $patch_path.NEWS
+cp $patch_path $patch_path.orig
+# bash
+cat $patch_path.mock $patch_path.tests > $patch_path
+filtered=$(cat $patch_path)
+if [ -n "${filtered}" ]; then
+ cat $patch_path.NEWS >> $patch_path
+ exitcode=0
+else
+ exitcode=1
+fi
+
+rm $patch_path.mock $patch_path.tests $patch_path.NEWS
+exit $exitcode
diff --git a/tools/pre-applypatch b/tools/pre-applypatch
new file mode 100755
index 0000000..28ab636
--- /dev/null
+++ b/tools/pre-applypatch
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+set -eu
+
+#. git-sh-setup
+echo "** in hook **"
+
+function test_version {
+ version=$1
+ host=$(ls ~/.virtualenvs/mock-$version-* -d | sed -e "s/^.*mock-$version-//")
+ if [ -z "$host" ]; then
+ echo "No host found for $version"
+ return 1
+ fi
+ echo testing $version in virtualenv mock-$version-$host on ssh host $host
+ ssh $host "cd work/mock && . ~/.virtualenvs/mock-$version-$host/bin/activate && pip install .[test] && unit2"
+}
+
+find . -name "*.pyc" -exec rm "{}" \;
+
+test_version 2.7
+test_version 3.3
+test_version 3.4
+test_version 3.5
+test_version cpython
+test_version pypy
+
+echo '** pre-apply complete and successful **'
diff --git a/tox.ini b/tox.ini
index 90ca455..d7fef31 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,12 +1,22 @@
[tox]
-envlist = py27,pypy,py34,py35,py36,py37,docs
+envlist = py27,pypy,py33,jython
[testenv]
-commands =
- {envbindir}/pytest {posargs}
+deps=unittest2
+commands={envbindir}/unit2 discover []
-[testenv:docs]
+[testenv:py27]
+commands=
+ {envbindir}/unit2 discover []
+ {envbindir}/sphinx-build -E -b doctest docs html
deps =
+ unittest2
sphinx
-commands =
- {envbindir}/python setup.py build_sphinx
+
+[testenv:py33]
+commands=
+ {envbindir}/python -m unittest discover []
+deps =
+
+# note for jython. Execute in tests directory:
+# rm `find . -name '*$py.class'` \ No newline at end of file
diff --git a/unittest.cfg b/unittest.cfg
new file mode 100644
index 0000000..b2d6f67
--- /dev/null
+++ b/unittest.cfg
@@ -0,0 +1,95 @@
+
+[unittest]
+plugins =
+ unittest2.plugins.debugger
+ unittest2.plugins.checker
+ unittest2.plugins.doctestloader
+ unittest2.plugins.matchregexp
+ unittest2.plugins.moduleloading
+ unittest2.plugins.testcoverage
+ unittest2.plugins.growl
+ unittest2.plugins.filtertests
+ unittest2.plugins.junitxml
+ unittest2.plugins.timed
+ unittest2.plugins.counttests
+ unittest2.plugins.logchannels
+
+excluded-plugins =
+
+# 0, 1 or 2 (default is 1)
+# quiet, normal or verbose
+# can be overriden at command line
+verbosity = normal
+
+# true or false
+# even if false can be switched on at command line
+catch =
+buffer =
+failfast =
+
+
+[matchregexp]
+always-on = False
+full-path = True
+
+[debugger]
+always-on = False
+errors-only = True
+
+[coverage]
+always-on = False
+config =
+report-html = False
+# only used if report-html is false
+annotate = False
+# defaults to './htmlcov/'
+html-directory =
+# if unset will output to console
+text-file =
+branch = False
+timid = False
+cover-pylib = False
+exclude-lines =
+ # Have to re-enable the standard pragma
+ pragma: no cover
+
+ # Don't complain about missing debug-only code:
+ def __repr__
+ if self\.debug
+
+ # Don't complain if tests don't hit defensive assertion code:
+ raise AssertionError
+ raise NotImplementedError
+
+ # Don't complain if non-runnable code isn't run:
+ if 0:
+ if __name__ == .__main__.
+
+ignore-errors = False
+modules =
+
+[growl]
+always-on = False
+
+[doctest]
+always-on = False
+
+[module-loading]
+always-on = False
+
+[checker]
+always-on = False
+pep8 = False
+pyflakes = True
+
+[junit-xml]
+always-on = False
+path = junit.xml
+
+[timed]
+always-on = True
+threshold = 0.01
+
+[count]
+always-on = True
+enhanced = False