Compare commits
11 commits
debian/boo
...
debian/mas
Author | SHA1 | Date | |
---|---|---|---|
|
1f809b8dbb | ||
|
110f3d85ec | ||
|
a909201310 | ||
|
8bf36e87d2 | ||
|
62436189d4 | ||
|
d29b628982 | ||
|
346b9c685b | ||
|
3013f06d2f | ||
|
c9fbf63242 | ||
|
fe05c079dd | ||
|
2b3250c1c1 |
64
.github/workflows/deploy.yml
vendored
64
.github/workflows/deploy.yml
vendored
|
@ -1,39 +1,67 @@
|
|||
name: deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Release version'
|
||||
required: true
|
||||
default: '1.2.3'
|
||||
|
||||
jobs:
|
||||
|
||||
deploy:
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build and Check Package
|
||||
uses: hynek/build-and-inspect-python-package@v1.5
|
||||
|
||||
deploy:
|
||||
needs: package
|
||||
runs-on: ubuntu-latest
|
||||
environment: deploy
|
||||
permissions:
|
||||
id-token: write # For PyPI trusted publishers.
|
||||
contents: write # For tag and release notes.
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download Package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
python-version: "3.7"
|
||||
- name: Install wheel
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build
|
||||
- name: Build package
|
||||
run: |
|
||||
python -m build
|
||||
name: Packages
|
||||
path: dist
|
||||
|
||||
- name: Publish package to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
uses: pypa/gh-action-pypi-publish@v1.8.5
|
||||
|
||||
- name: Push tag
|
||||
run: |
|
||||
git config user.name "pytest bot"
|
||||
git config user.email "pytestbot@gmail.com"
|
||||
git tag --annotate --message=v${{ github.event.inputs.version }} v${{ github.event.inputs.version }} ${{ github.sha }}
|
||||
git push origin v${{ github.event.inputs.version }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_token }}
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
pip install pypandoc
|
||||
sudo apt-get install pandoc
|
||||
python scripts/gen-release-notes.py
|
||||
|
||||
- name: GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: scripts/latest-release-notes.md
|
||||
files: dist/*
|
||||
tag_name: v${{ github.event.inputs.version }}
|
||||
|
|
55
.github/workflows/test.yml
vendored
55
.github/workflows/test.yml
vendored
|
@ -1,38 +1,67 @@
|
|||
name: test
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "test-me-*"
|
||||
|
||||
pull_request:
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build and Check Package
|
||||
uses: hynek/build-and-inspect-python-package@v1.5
|
||||
|
||||
test:
|
||||
|
||||
needs: [package]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python: ["3.7", "3.8", "3.9", "3.10"]
|
||||
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
tox_env: ["py"]
|
||||
include:
|
||||
- python: "3.7"
|
||||
tox_env: "py37"
|
||||
- python: "3.8"
|
||||
tox_env: "py38"
|
||||
- python: "3.9"
|
||||
tox_env: "py39"
|
||||
- python: "3.10"
|
||||
tox_env: "py310"
|
||||
- python: "3.12"
|
||||
os: ubuntu-latest
|
||||
tox_env: "norewrite"
|
||||
- python: "3.12"
|
||||
os: windows-latest
|
||||
tox_env: "norewrite"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download Package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Packages
|
||||
path: dist
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
|
||||
- name: Install tox
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
tox -e ${{ matrix.tox_env }}
|
||||
tox run -e ${{ matrix.tox_env }} --installpkg `find dist/*.tar.gz`
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
exclude: '^($|.*\.bin)'
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.6.0
|
||||
rev: 23.9.1
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--safe, --quiet]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
|
@ -18,13 +18,13 @@ repos:
|
|||
files: ^(CHANGELOG.rst|README.rst|HOWTORELEASE.rst|changelog/.*)$
|
||||
language: python
|
||||
additional_dependencies: [pygments, restructuredtext_lint]
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v3.3.0
|
||||
- repo: https://github.com/asottile/reorder-python-imports
|
||||
rev: v3.12.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ['--application-directories=.:src']
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.961 # NOTE: keep this in sync with tox.ini
|
||||
rev: v1.6.0 # NOTE: keep this in sync with tox.ini
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: ^(src|tests)
|
||||
|
|
15
.readthedocs.yml
Normal file
15
.readthedocs.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
fail_on_warning: true
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
- path: .
|
|
@ -1,10 +1,56 @@
|
|||
Releases
|
||||
========
|
||||
|
||||
3.12.0 (2023-10-19)
|
||||
-------------------
|
||||
|
||||
* Added support for Python 3.12.
|
||||
* Dropped support for EOL Python 3.7.
|
||||
* ``mocker.resetall()`` now also resets mocks created by ``mocker.create_autospec`` (`#390`_).
|
||||
|
||||
.. _#390: https://github.com/pytest-dev/pytest-mock/pull/390
|
||||
|
||||
3.11.1 (2023-06-15)
|
||||
-------------------
|
||||
|
||||
(This release source code is identical to ``3.11.0`` except a small internal fix to deployment/CI)
|
||||
|
||||
* Fixed introspection for failed ``assert_has_calls`` (`#365`_).
|
||||
|
||||
* Updated type annotations for ``mocker.patch`` and ``mocker.spy`` (`#364`_).
|
||||
|
||||
.. _#365: https://github.com/pytest-dev/pytest-mock/pull/365
|
||||
.. _#364: https://github.com/pytest-dev/pytest-mock/pull/364
|
||||
|
||||
3.11.0 (2023-06-15)
|
||||
-------------------
|
||||
|
||||
* Fixed introspection for failed ``assert_has_calls`` (`#365`_).
|
||||
|
||||
* Updated type annotations for ``mocker.patch`` and ``mocker.spy`` (`#364`_).
|
||||
|
||||
.. _#365: https://github.com/pytest-dev/pytest-mock/pull/365
|
||||
.. _#364: https://github.com/pytest-dev/pytest-mock/pull/364
|
||||
|
||||
|
||||
3.10.0 (2022-10-05)
|
||||
-------------------
|
||||
|
||||
* Added new ``mocker.stop(m)`` method to stop specific ``mocker.patch`` or ``mocker.spy`` calls (`#319`_).
|
||||
|
||||
.. _#319: https://github.com/pytest-dev/pytest-mock/pull/319
|
||||
|
||||
3.9.0 (2022-09-28)
|
||||
------------------
|
||||
|
||||
* Expose ``NonCallableMagicMock`` via the ``mocker`` fixture (`#318`_).
|
||||
|
||||
.. _#318: https://github.com/pytest-dev/pytest-mock/pull/318
|
||||
|
||||
3.8.2 (2022-07-05)
|
||||
------------------
|
||||
|
||||
- Fixed `AsyncMock` support for Python 3.7+ in `mocker.async_stub` (`#302`_).
|
||||
- Fixed ``AsyncMock`` support for Python 3.7+ in ``mocker.async_stub`` (`#302`_).
|
||||
|
||||
.. _#302: https://github.com/pytest-dev/pytest-mock/pull/302
|
||||
|
||||
|
|
18
PKG-INFO
18
PKG-INFO
|
@ -1,11 +1,15 @@
|
|||
Metadata-Version: 2.1
|
||||
Name: pytest-mock
|
||||
Version: 3.8.2
|
||||
Version: 3.12.0
|
||||
Summary: Thin-wrapper around the mock package for easier use with pytest
|
||||
Home-page: https://github.com/pytest-dev/pytest-mock/
|
||||
Author: Bruno Oliveira
|
||||
Author-email: nicoddemus@gmail.com
|
||||
License: MIT
|
||||
Project-URL: Documentation, https://pytest-mock.readthedocs.io/en/latest/
|
||||
Project-URL: Changelog, https://pytest-mock.readthedocs.io/en/latest/changelog.html
|
||||
Project-URL: Source, https://github.com/pytest-dev/pytest-mock/
|
||||
Project-URL: Tracker, https://github.com/pytest-dev/pytest-mock/issues
|
||||
Keywords: pytest mock
|
||||
Platform: any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
|
@ -14,15 +18,21 @@ Classifier: Intended Audience :: Developers
|
|||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Topic :: Software Development :: Testing
|
||||
Requires-Python: >=3.7
|
||||
Provides-Extra: dev
|
||||
Requires-Python: >=3.8
|
||||
Description-Content-Type: text/x-rst
|
||||
License-File: LICENSE
|
||||
Requires-Dist: pytest>=5.0
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pre-commit; extra == "dev"
|
||||
Requires-Dist: tox; extra == "dev"
|
||||
Requires-Dist: pytest-asyncio; extra == "dev"
|
||||
|
||||
===========
|
||||
pytest-mock
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Here are the steps on how to make a new release.
|
||||
|
||||
1. Create a ``release-VERSION`` branch from ``upstream/master``.
|
||||
1. Create a ``release-VERSION`` branch from ``upstream/main``.
|
||||
2. Update ``CHANGELOG.rst``.
|
||||
3. Push a branch with the changes.
|
||||
4. Once all builds pass, push a tag to ``upstream``.
|
||||
3. Push the branch to ``upstream``.
|
||||
4. Once all tests pass, start the ``deploy`` workflow manually.
|
||||
5. Merge the PR.
|
||||
|
|
26
debian/changelog
vendored
26
debian/changelog
vendored
|
@ -1,3 +1,29 @@
|
|||
pytest-mock (3.12.0-1) unstable; urgency=medium
|
||||
|
||||
* Team upload.
|
||||
* New upstream version 3.12.0
|
||||
* Drop Sphinx theme patch; furo is available
|
||||
* Explicitly clean egg info
|
||||
|
||||
-- Timo Röhling <roehling@debian.org> Mon, 13 Nov 2023 00:46:56 +0100
|
||||
|
||||
pytest-mock (3.11.1-2) unstable; urgency=medium
|
||||
|
||||
* Team upload.
|
||||
* Regenerate egg-info because it is needed for the unit tests
|
||||
(Closes: #1052904)
|
||||
|
||||
-- Timo Röhling <roehling@debian.org> Fri, 13 Oct 2023 19:40:04 +0200
|
||||
|
||||
pytest-mock (3.11.1-1) unstable; urgency=medium
|
||||
|
||||
* Team upload.
|
||||
* New upstream version 3.11.1
|
||||
- Stop importing deprecated py.code module
|
||||
* Bump Standards-Version to 4.6.2
|
||||
|
||||
-- Timo Röhling <roehling@debian.org> Wed, 05 Jul 2023 14:33:45 +0200
|
||||
|
||||
pytest-mock (3.8.2-3) unstable; urgency=medium
|
||||
|
||||
[ Debian Janitor ]
|
||||
|
|
1
debian/clean
vendored
Normal file
1
debian/clean
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
src/*.egg-info/
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -6,6 +6,7 @@ Priority: optional
|
|||
Build-Depends: debhelper-compat (= 13),
|
||||
dh-python,
|
||||
dh-sequence-python3,
|
||||
furo <!nodoc>,
|
||||
python3-all,
|
||||
python3-mock,
|
||||
python3-pytest (>= 7.1.2),
|
||||
|
@ -13,9 +14,8 @@ Build-Depends: debhelper-compat (= 13),
|
|||
python3-setuptools,
|
||||
python3-setuptools-scm,
|
||||
python3-sphinx-copybutton <!nodoc>,
|
||||
python3-sphinx-rtd-theme <!nodoc>,
|
||||
sphinx <!nodoc>
|
||||
Standards-Version: 4.6.1
|
||||
Standards-Version: 4.6.2
|
||||
Vcs-Browser: https://salsa.debian.org/python-team/packages/pytest-mock
|
||||
Vcs-Git: https://salsa.debian.org/python-team/packages/pytest-mock.git
|
||||
Homepage: https://github.com/pytest-dev/pytest-mock/
|
||||
|
|
18
debian/patches/change_sphinx_theme.patch
vendored
18
debian/patches/change_sphinx_theme.patch
vendored
|
@ -1,18 +0,0 @@
|
|||
Description: Use already packaged theme for documentation
|
||||
Upstream uses the furo theme, which has not been packaged for Debian.
|
||||
We switch to the common RTD theme instead.
|
||||
Forwarded: not-needed
|
||||
Author: Julian Gilbey <jdg@debian.org>
|
||||
Last-Update: 2022-07-15
|
||||
|
||||
--- a/docs/conf.py
|
||||
+++ b/docs/conf.py
|
||||
@@ -42,7 +42,7 @@
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
-html_theme = "furo"
|
||||
+html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
1
debian/patches/series
vendored
1
debian/patches/series
vendored
|
@ -1 +0,0 @@
|
|||
change_sphinx_theme.patch
|
4
debian/rules
vendored
4
debian/rules
vendored
|
@ -7,9 +7,9 @@ export PYBUILD_NAME=pytest-mock
|
|||
# The --assert=plain is needed to skip four tests; see
|
||||
# https://github.com/pytest-dev/pytest-mock/issues/102
|
||||
# for more information.
|
||||
export PYBUILD_BEFORE_TEST=cp -r {dir}/src/*.egg-info {build_dir}
|
||||
export PYBUILD_BEFORE_TEST={interpreter} setup.py egg_info && cp -r {dir}/src/*.egg-info {build_dir}
|
||||
export PYBUILD_TEST_ARGS=--assert=plain {dir}/tests
|
||||
export PYBUILD_AFTER_TEST=rm -rf {build_dir}/*.egg-info
|
||||
export PYBUILD_AFTER_TEST=rm -rf {build_dir}/*.egg-info {dir}/src/*.egg-info
|
||||
|
||||
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||
%:
|
||||
|
|
2
docs/_static/.gitignore
vendored
Normal file
2
docs/_static/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -15,7 +15,7 @@ Tests are run with ``tox``, you can run the baseline environments before submitt
|
|||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e py38,linting
|
||||
$ tox -e py38
|
||||
|
||||
Style checks and formatting are done automatically during commit courtesy of
|
||||
`pre-commit <https://pre-commit.com>`_.
|
||||
|
|
|
@ -100,23 +100,3 @@ to improve the flow of the test:
|
|||
# ...
|
||||
|
||||
But this is arguably a little more complex than using ``pytest-mock``.
|
||||
|
||||
Usage as context manager
|
||||
------------------------
|
||||
|
||||
Although mocker's API is intentionally the same as ``mock.patch``'s, its use
|
||||
as context manager and function decorator is **not** supported through the
|
||||
fixture:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_context_manager(mocker):
|
||||
a = A()
|
||||
with mocker.patch.object(a, 'doIt', return_value=True, autospec=True): # DO NOT DO THIS
|
||||
assert a.doIt() == True
|
||||
|
||||
The purpose of this plugin is to make the use of context managers and
|
||||
function decorators for mocking unnecessary, so it will emit a warning when used as such.
|
||||
|
||||
If you really intend to mock a context manager, ``mocker.patch.context_manager`` exists
|
||||
which won't issue the above warning.
|
||||
|
|
|
@ -21,6 +21,7 @@ The supported methods are:
|
|||
* `mocker.patch.multiple <https://docs.python.org/3/library/unittest.mock.html#patch-multiple>`_
|
||||
* `mocker.patch.dict <https://docs.python.org/3/library/unittest.mock.html#patch-dict>`_
|
||||
* `mocker.stopall <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch.stopall>`_
|
||||
* `mocker.stop <https://docs.python.org/3/library/unittest.mock.html#patch-methods-start-and-stop>`_
|
||||
* ``mocker.resetall()``: calls `reset_mock() <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.reset_mock>`_ in all mocked objects up to this point.
|
||||
|
||||
Also, as a convenience, these names from the ``mock`` module are accessible directly from ``mocker``:
|
||||
|
@ -94,6 +95,27 @@ As of version 3.0.0, ``mocker.spy`` also works with ``async def`` functions.
|
|||
|
||||
.. _#175: https://github.com/pytest-dev/pytest-mock/issues/175
|
||||
|
||||
As of version 3.10, spying can be also selectively stopped.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_with_unspy(mocker):
|
||||
class Foo:
|
||||
def bar(self):
|
||||
return 42
|
||||
|
||||
spy = mocker.spy(Foo, "bar")
|
||||
foo = Foo()
|
||||
assert foo.bar() == 42
|
||||
assert spy.call_count == 1
|
||||
mocker.stop(spy)
|
||||
assert foo.bar() == 42
|
||||
assert spy.call_count == 1
|
||||
|
||||
|
||||
``mocker.stop()`` can also be used by ``mocker.patch`` calls.
|
||||
|
||||
|
||||
Stub
|
||||
----
|
||||
|
||||
|
@ -114,3 +136,33 @@ It may receive an optional name that is shown in its ``repr``, useful for debugg
|
|||
.. seealso::
|
||||
|
||||
``async_stub`` method, which actually the same as ``stub`` but makes async stub.
|
||||
|
||||
|
||||
Usage as context manager
|
||||
------------------------
|
||||
|
||||
Although mocker's API is intentionally the same as ``mock.patch``'s, its use
|
||||
as context manager and function decorator is **not** supported through the
|
||||
fixture:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_context_manager(mocker):
|
||||
a = A()
|
||||
with mocker.patch.object(a, 'doIt', return_value=True, autospec=True): # DO NOT DO THIS
|
||||
assert a.doIt() == True
|
||||
|
||||
The purpose of this plugin is to make the use of context managers and
|
||||
function decorators for mocking unnecessary, so it will emit a warning when used as such.
|
||||
|
||||
If you really intend to mock a context manager, ``mocker.patch.context_manager`` exists
|
||||
which won't issue the above warning.
|
||||
|
||||
Where to patch
|
||||
--------------
|
||||
|
||||
A common issue where mocking appears not to be working is patching in the wrong place.
|
||||
|
||||
See this `section in the unittest docs <https://docs.python.org/3/library/unittest.mock.html#where-to-patch>`__ which provides a comprehensive explanation.
|
||||
|
||||
Also see this excellent blog post: `Why your mock doesn't work <https://nedbatchelder.com/blog/201908/why_your_mock_doesnt_work.html>`__.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
"""
|
||||
Generates the release notes for the latest release, in Markdown.
|
||||
|
||||
Convert CHANGELOG.rst to Markdown, and extracts just the latest release.
|
||||
|
||||
Writes to ``scripts/latest-release-notes.md``, which can be
|
||||
used with https://github.com/softprops/action-gh-release.
|
||||
1. Extracts the latest release from the CHANGELOG.rst file.
|
||||
2. Converts it to Markdown using pypandoc.
|
||||
3. Writes to ``scripts/latest-release-notes.md``, which can be
|
||||
used with https://github.com/softprops/action-gh-release.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -12,20 +12,36 @@ import pypandoc
|
|||
|
||||
this_dir = Path(__file__).parent
|
||||
rst_text = (this_dir.parent / "CHANGELOG.rst").read_text(encoding="UTF-8")
|
||||
md_text = pypandoc.convert_text(
|
||||
rst_text, "md", format="rst", extra_args=["--wrap=preserve"]
|
||||
)
|
||||
|
||||
output_lines = []
|
||||
first_heading_found = False
|
||||
for line in md_text.splitlines():
|
||||
if line.startswith("# "):
|
||||
if first_heading_found:
|
||||
capture = False
|
||||
for line in rst_text.splitlines():
|
||||
# Only start capturing after the latest release section.
|
||||
if line.startswith("-------"):
|
||||
capture = not capture
|
||||
if not capture:
|
||||
# We only need to capture the latest release, so stop.
|
||||
break
|
||||
first_heading_found = True
|
||||
else:
|
||||
continue
|
||||
|
||||
if capture:
|
||||
output_lines.append(line)
|
||||
|
||||
# Drop last line, as it contains the previous release section title.
|
||||
del output_lines[-1]
|
||||
|
||||
trimmed_rst = "\n".join(output_lines).strip()
|
||||
print(">>Trimmed RST follows:")
|
||||
print(trimmed_rst)
|
||||
print(">>Trimmed RST ends")
|
||||
|
||||
md_text = pypandoc.convert_text(
|
||||
trimmed_rst, "md", format="rst", extra_args=["--wrap=preserve"]
|
||||
)
|
||||
print(">>Converted Markdown follows:")
|
||||
print(md_text)
|
||||
print(">>Converted Markdown ends")
|
||||
|
||||
output_fn = this_dir / "latest-release-notes.md"
|
||||
output_fn.write_text("\n".join(output_lines), encoding="UTF-8")
|
||||
output_fn.write_text(md_text, encoding="UTF-8")
|
||||
print(output_fn, "generated.")
|
||||
|
|
14
setup.py
14
setup.py
|
@ -1,5 +1,3 @@
|
|||
from io import open
|
||||
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
|
@ -12,7 +10,7 @@ setup(
|
|||
package_data={
|
||||
"pytest_mock": ["py.typed"],
|
||||
},
|
||||
python_requires=">=3.7",
|
||||
python_requires=">=3.8",
|
||||
install_requires=["pytest>=5.0"],
|
||||
use_scm_version={"write_to": "src/pytest_mock/_version.py"},
|
||||
setup_requires=["setuptools_scm"],
|
||||
|
@ -22,6 +20,7 @@ setup(
|
|||
author_email="nicoddemus@gmail.com",
|
||||
description="Thin-wrapper around the mock package for easier use with pytest",
|
||||
long_description=open("README.rst", encoding="utf-8").read(),
|
||||
long_description_content_type="text/x-rst",
|
||||
keywords="pytest mock",
|
||||
extras_require={"dev": ["pre-commit", "tox", "pytest-asyncio"]},
|
||||
classifiers=[
|
||||
|
@ -31,11 +30,18 @@ setup(
|
|||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development :: Testing",
|
||||
],
|
||||
project_urls={
|
||||
"Documentation": "https://pytest-mock.readthedocs.io/en/latest/",
|
||||
"Changelog": "https://pytest-mock.readthedocs.io/en/latest/changelog.html",
|
||||
"Source": "https://github.com/pytest-dev/pytest-mock/",
|
||||
"Tracker": "https://github.com/pytest-dev/pytest-mock/issues",
|
||||
},
|
||||
)
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
Metadata-Version: 2.1
|
||||
Name: pytest-mock
|
||||
Version: 3.8.2
|
||||
Version: 3.12.0
|
||||
Summary: Thin-wrapper around the mock package for easier use with pytest
|
||||
Home-page: https://github.com/pytest-dev/pytest-mock/
|
||||
Author: Bruno Oliveira
|
||||
Author-email: nicoddemus@gmail.com
|
||||
License: MIT
|
||||
Project-URL: Documentation, https://pytest-mock.readthedocs.io/en/latest/
|
||||
Project-URL: Changelog, https://pytest-mock.readthedocs.io/en/latest/changelog.html
|
||||
Project-URL: Source, https://github.com/pytest-dev/pytest-mock/
|
||||
Project-URL: Tracker, https://github.com/pytest-dev/pytest-mock/issues
|
||||
Keywords: pytest mock
|
||||
Platform: any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
|
@ -14,15 +18,21 @@ Classifier: Intended Audience :: Developers
|
|||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Topic :: Software Development :: Testing
|
||||
Requires-Python: >=3.7
|
||||
Provides-Extra: dev
|
||||
Requires-Python: >=3.8
|
||||
Description-Content-Type: text/x-rst
|
||||
License-File: LICENSE
|
||||
Requires-Dist: pytest>=5.0
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pre-commit; extra == "dev"
|
||||
Requires-Dist: tox; extra == "dev"
|
||||
Requires-Dist: pytest-asyncio; extra == "dev"
|
||||
|
||||
===========
|
||||
pytest-mock
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.gitignore
|
||||
.pre-commit-config.yaml
|
||||
.readthedocs.yml
|
||||
CHANGELOG.rst
|
||||
LICENSE
|
||||
README.rst
|
||||
|
@ -19,6 +20,7 @@ docs/index.rst
|
|||
docs/remarks.rst
|
||||
docs/requirements.txt
|
||||
docs/usage.rst
|
||||
docs/_static/.gitignore
|
||||
scripts/gen-release-notes.py
|
||||
src/pytest_mock/__init__.py
|
||||
src/pytest_mock/_util.py
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
# coding: utf-8
|
||||
# file generated by setuptools_scm
|
||||
# don't change, don't track in version control
|
||||
__version__ = version = '3.8.2'
|
||||
__version_tuple__ = version_tuple = (3, 8, 2)
|
||||
TYPE_CHECKING = False
|
||||
if TYPE_CHECKING:
|
||||
from typing import Tuple, Union
|
||||
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
||||
else:
|
||||
VERSION_TUPLE = object
|
||||
|
||||
version: str
|
||||
__version__: str
|
||||
__version_tuple__: VERSION_TUPLE
|
||||
version_tuple: VERSION_TUPLE
|
||||
|
||||
__version__ = version = '3.12.0'
|
||||
__version_tuple__ = version_tuple = (3, 12, 0)
|
||||
|
|
|
@ -27,10 +27,16 @@ from ._util import parse_ini_boolean
|
|||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
if sys.version_info[:2] > (3, 7):
|
||||
if sys.version_info >= (3, 8):
|
||||
AsyncMockType = unittest.mock.AsyncMock
|
||||
MockType = Union[
|
||||
unittest.mock.MagicMock,
|
||||
unittest.mock.AsyncMock,
|
||||
unittest.mock.NonCallableMagicMock,
|
||||
]
|
||||
else:
|
||||
AsyncMockType = Any
|
||||
MockType = Union[unittest.mock.MagicMock, unittest.mock.NonCallableMagicMock]
|
||||
|
||||
|
||||
class PytestMockWarning(UserWarning):
|
||||
|
@ -44,28 +50,36 @@ class MockerFixture:
|
|||
"""
|
||||
|
||||
def __init__(self, config: Any) -> None:
|
||||
self._patches = [] # type: List[Any]
|
||||
self._mocks = [] # type: List[Any]
|
||||
self._patches_and_mocks: List[Tuple[Any, unittest.mock.MagicMock]] = []
|
||||
self.mock_module = mock_module = get_mock_module(config)
|
||||
self.patch = self._Patcher(
|
||||
self._patches, self._mocks, mock_module
|
||||
self._patches_and_mocks, mock_module
|
||||
) # type: MockerFixture._Patcher
|
||||
# aliases for convenience
|
||||
self.Mock = mock_module.Mock
|
||||
self.MagicMock = mock_module.MagicMock
|
||||
self.NonCallableMock = mock_module.NonCallableMock
|
||||
self.NonCallableMagicMock = mock_module.NonCallableMagicMock
|
||||
self.PropertyMock = mock_module.PropertyMock
|
||||
if hasattr(mock_module, "AsyncMock"):
|
||||
self.AsyncMock = mock_module.AsyncMock
|
||||
self.call = mock_module.call
|
||||
self.ANY = mock_module.ANY
|
||||
self.DEFAULT = mock_module.DEFAULT
|
||||
self.create_autospec = mock_module.create_autospec
|
||||
self.sentinel = mock_module.sentinel
|
||||
self.mock_open = mock_module.mock_open
|
||||
if hasattr(mock_module, "seal"):
|
||||
self.seal = mock_module.seal
|
||||
|
||||
def create_autospec(
|
||||
self, spec: Any, spec_set: bool = False, instance: bool = False, **kwargs: Any
|
||||
) -> MockType:
|
||||
m: MockType = self.mock_module.create_autospec(
|
||||
spec, spec_set, instance, **kwargs
|
||||
)
|
||||
self._patches_and_mocks.append((None, m))
|
||||
return m
|
||||
|
||||
def resetall(
|
||||
self, *, return_value: bool = False, side_effect: bool = False
|
||||
) -> None:
|
||||
|
@ -81,8 +95,10 @@ class MockerFixture:
|
|||
else:
|
||||
supports_reset_mock_with_args = (self.Mock,)
|
||||
|
||||
for m in self._mocks:
|
||||
for p, m in self._patches_and_mocks:
|
||||
# See issue #237.
|
||||
if not hasattr(m, "reset_mock"):
|
||||
continue
|
||||
if isinstance(m, supports_reset_mock_with_args):
|
||||
m.reset_mock(return_value=return_value, side_effect=side_effect)
|
||||
else:
|
||||
|
@ -93,12 +109,25 @@ class MockerFixture:
|
|||
Stop all patchers started by this fixture. Can be safely called multiple
|
||||
times.
|
||||
"""
|
||||
for p in reversed(self._patches):
|
||||
p.stop()
|
||||
self._patches[:] = []
|
||||
self._mocks[:] = []
|
||||
for p, m in reversed(self._patches_and_mocks):
|
||||
if p is not None:
|
||||
p.stop()
|
||||
self._patches_and_mocks.clear()
|
||||
|
||||
def spy(self, obj: object, name: str) -> unittest.mock.MagicMock:
|
||||
def stop(self, mock: unittest.mock.MagicMock) -> None:
|
||||
"""
|
||||
Stops a previous patch or spy call by passing the ``MagicMock`` object
|
||||
returned by it.
|
||||
"""
|
||||
for index, (p, m) in enumerate(self._patches_and_mocks):
|
||||
if mock is m:
|
||||
p.stop()
|
||||
del self._patches_and_mocks[index]
|
||||
break
|
||||
else:
|
||||
raise ValueError("This mock object is not registered")
|
||||
|
||||
def spy(self, obj: object, name: str) -> MockType:
|
||||
"""
|
||||
Create a spy of method. It will run method normally, but it is now
|
||||
possible to use `mock` call features with it, like call count.
|
||||
|
@ -185,23 +214,21 @@ class MockerFixture:
|
|||
|
||||
DEFAULT = object()
|
||||
|
||||
def __init__(self, patches, mocks, mock_module):
|
||||
self._patches = patches
|
||||
self._mocks = mocks
|
||||
def __init__(self, patches_and_mocks, mock_module):
|
||||
self.__patches_and_mocks = patches_and_mocks
|
||||
self.mock_module = mock_module
|
||||
|
||||
def _start_patch(
|
||||
self, mock_func: Any, warn_on_mock_enter: bool, *args: Any, **kwargs: Any
|
||||
) -> unittest.mock.MagicMock:
|
||||
) -> MockType:
|
||||
"""Patches something by calling the given function from the mock
|
||||
module, registering the patch to stop it later and returns the
|
||||
mock object resulting from the mock call.
|
||||
"""
|
||||
p = mock_func(*args, **kwargs)
|
||||
mocked = p.start() # type: unittest.mock.MagicMock
|
||||
self._patches.append(p)
|
||||
mocked: MockType = p.start()
|
||||
self.__patches_and_mocks.append((p, mocked))
|
||||
if hasattr(mocked, "reset_mock"):
|
||||
self._mocks.append(mocked)
|
||||
# check if `mocked` is actually a mock object, as depending on autospec or target
|
||||
# parameters `mocked` can be anything
|
||||
if hasattr(mocked, "__enter__") and warn_on_mock_enter:
|
||||
|
@ -213,7 +240,7 @@ class MockerFixture:
|
|||
"Mocks returned by pytest-mock do not need to be used as context managers. "
|
||||
"The mocker fixture automatically undoes mocking at the end of a test. "
|
||||
"This warning can be ignored if it was triggered by mocking a context manager. "
|
||||
"https://github.com/pytest-dev/pytest-mock#note-about-usage-as-context-manager",
|
||||
"https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager",
|
||||
PytestMockWarning,
|
||||
stacklevel=depth,
|
||||
)
|
||||
|
@ -230,7 +257,7 @@ class MockerFixture:
|
|||
autospec: Optional[object] = None,
|
||||
new_callable: object = None,
|
||||
**kwargs: Any
|
||||
) -> unittest.mock.MagicMock:
|
||||
) -> MockType:
|
||||
"""API to mock.patch.object"""
|
||||
if new is self.DEFAULT:
|
||||
new = self.mock_module.DEFAULT
|
||||
|
@ -259,7 +286,7 @@ class MockerFixture:
|
|||
autospec: Optional[builtins.object] = None,
|
||||
new_callable: builtins.object = None,
|
||||
**kwargs: Any
|
||||
) -> unittest.mock.MagicMock:
|
||||
) -> MockType:
|
||||
"""This is equivalent to mock.patch.object except that the returned mock
|
||||
does not issue a warning when used as a context manager."""
|
||||
if new is self.DEFAULT:
|
||||
|
@ -287,7 +314,7 @@ class MockerFixture:
|
|||
autospec: Optional[builtins.object] = None,
|
||||
new_callable: Optional[builtins.object] = None,
|
||||
**kwargs: Any
|
||||
) -> Dict[str, unittest.mock.MagicMock]:
|
||||
) -> Dict[str, MockType]:
|
||||
"""API to mock.patch.multiple"""
|
||||
return self._start_patch(
|
||||
self.mock_module.patch.multiple,
|
||||
|
@ -329,7 +356,7 @@ class MockerFixture:
|
|||
autospec: Optional[builtins.object] = ...,
|
||||
new_callable: None = ...,
|
||||
**kwargs: Any
|
||||
) -> unittest.mock.MagicMock:
|
||||
) -> MockType:
|
||||
...
|
||||
|
||||
@overload
|
||||
|
@ -455,6 +482,54 @@ def assert_wrapper(
|
|||
raise e
|
||||
|
||||
|
||||
def assert_has_calls_wrapper(
|
||||
__wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
|
||||
) -> None:
|
||||
__tracebackhide__ = True
|
||||
try:
|
||||
__wrapped_mock_method__(*args, **kwargs)
|
||||
return
|
||||
except AssertionError as e:
|
||||
any_order = kwargs.get("any_order", False)
|
||||
if getattr(e, "_mock_introspection_applied", 0) or any_order:
|
||||
msg = str(e)
|
||||
else:
|
||||
__mock_self = args[0]
|
||||
msg = str(e)
|
||||
if __mock_self.call_args_list is not None:
|
||||
actual_calls = list(__mock_self.call_args_list)
|
||||
expect_calls = args[1]
|
||||
introspection = ""
|
||||
from itertools import zip_longest
|
||||
|
||||
for actual_call, expect_call in zip_longest(actual_calls, expect_calls):
|
||||
if actual_call is not None:
|
||||
actual_args, actual_kwargs = actual_call
|
||||
else:
|
||||
actual_args = tuple()
|
||||
actual_kwargs = {}
|
||||
|
||||
if expect_call is not None:
|
||||
_, expect_args, expect_kwargs = expect_call
|
||||
else:
|
||||
expect_args = tuple()
|
||||
expect_kwargs = {}
|
||||
|
||||
try:
|
||||
assert actual_args == expect_args
|
||||
except AssertionError as e_args:
|
||||
introspection += "\nArgs:\n" + str(e_args)
|
||||
try:
|
||||
assert actual_kwargs == expect_kwargs
|
||||
except AssertionError as e_kwargs:
|
||||
introspection += "\nKwargs:\n" + str(e_kwargs)
|
||||
if introspection:
|
||||
msg += "\n\npytest introspection follows:\n" + introspection
|
||||
e = AssertionError(msg)
|
||||
e._mock_introspection_applied = True # type:ignore[attr-defined]
|
||||
raise e
|
||||
|
||||
|
||||
def wrap_assert_not_called(*args: Any, **kwargs: Any) -> None:
|
||||
__tracebackhide__ = True
|
||||
assert_wrapper(_mock_module_originals["assert_not_called"], *args, **kwargs)
|
||||
|
@ -477,7 +552,9 @@ def wrap_assert_called_once_with(*args: Any, **kwargs: Any) -> None:
|
|||
|
||||
def wrap_assert_has_calls(*args: Any, **kwargs: Any) -> None:
|
||||
__tracebackhide__ = True
|
||||
assert_wrapper(_mock_module_originals["assert_has_calls"], *args, **kwargs)
|
||||
assert_has_calls_wrapper(
|
||||
_mock_module_originals["assert_has_calls"], *args, **kwargs
|
||||
)
|
||||
|
||||
|
||||
def wrap_assert_any_call(*args: Any, **kwargs: Any) -> None:
|
||||
|
|
|
@ -60,6 +60,15 @@ class UnixFS:
|
|||
return os.listdir(path)
|
||||
|
||||
|
||||
class TestObject:
|
||||
"""
|
||||
Class that is used for testing create_autospec with child mocks
|
||||
"""
|
||||
|
||||
def run(self) -> str:
|
||||
return "not mocked"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def check_unix_fs_mocked(
|
||||
tmpdir: Any, mocker: MockerFixture
|
||||
|
@ -156,10 +165,10 @@ def test_mock_patch_dict_resetall(mocker: MockerFixture) -> None:
|
|||
[
|
||||
"ANY",
|
||||
"call",
|
||||
"create_autospec",
|
||||
"MagicMock",
|
||||
"Mock",
|
||||
"mock_open",
|
||||
"NonCallableMagicMock",
|
||||
"NonCallableMock",
|
||||
"PropertyMock",
|
||||
"sentinel",
|
||||
|
@ -184,23 +193,35 @@ def test_mocker_resetall(mocker: MockerFixture) -> None:
|
|||
listdir = mocker.patch("os.listdir", return_value="foo")
|
||||
open = mocker.patch("os.open", side_effect=["bar", "baz"])
|
||||
|
||||
mocked_object = mocker.create_autospec(TestObject)
|
||||
mocked_object.run.return_value = "mocked"
|
||||
|
||||
assert listdir("/tmp") == "foo"
|
||||
assert open("/tmp/foo.txt") == "bar"
|
||||
assert mocked_object.run() == "mocked"
|
||||
listdir.assert_called_once_with("/tmp")
|
||||
open.assert_called_once_with("/tmp/foo.txt")
|
||||
mocked_object.run.assert_called_once()
|
||||
|
||||
mocker.resetall()
|
||||
|
||||
assert not listdir.called
|
||||
assert not open.called
|
||||
assert not mocked_object.called
|
||||
assert listdir.return_value == "foo"
|
||||
assert list(open.side_effect) == ["baz"]
|
||||
assert mocked_object.run.return_value == "mocked"
|
||||
|
||||
mocker.resetall(return_value=True, side_effect=True)
|
||||
|
||||
assert isinstance(listdir.return_value, mocker.Mock)
|
||||
assert open.side_effect is None
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
# The reset on child mocks have been implemented in 3.9
|
||||
# https://bugs.python.org/issue38932
|
||||
assert mocked_object.run.return_value != "mocked"
|
||||
|
||||
|
||||
class TestMockerStub:
|
||||
def test_call(self, mocker: MockerFixture) -> None:
|
||||
|
@ -418,7 +439,6 @@ def test_class_method_with_metaclass_spy(mocker: MockerFixture) -> None:
|
|||
pass
|
||||
|
||||
class Foo:
|
||||
|
||||
__metaclass__ = MetaFoo
|
||||
|
||||
@classmethod
|
||||
|
@ -630,6 +650,86 @@ def test_assert_has_calls(mocker: MockerFixture) -> None:
|
|||
stub.assert_has_calls([mocker.call("bar")])
|
||||
|
||||
|
||||
def test_assert_has_calls_multiple_calls(mocker: MockerFixture) -> None:
|
||||
stub = mocker.stub()
|
||||
stub("foo")
|
||||
stub("bar")
|
||||
stub("baz")
|
||||
stub.assert_has_calls([mocker.call("foo"), mocker.call("bar"), mocker.call("baz")])
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls(
|
||||
[
|
||||
mocker.call("foo"),
|
||||
mocker.call("bar"),
|
||||
mocker.call("baz"),
|
||||
mocker.call("bat"),
|
||||
]
|
||||
)
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls(
|
||||
[mocker.call("foo"), mocker.call("baz"), mocker.call("bar")]
|
||||
)
|
||||
|
||||
|
||||
def test_assert_has_calls_multiple_calls_subset(mocker: MockerFixture) -> None:
|
||||
stub = mocker.stub()
|
||||
stub("foo")
|
||||
stub("bar")
|
||||
stub("baz")
|
||||
stub.assert_has_calls([mocker.call("bar"), mocker.call("baz")])
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls([mocker.call("foo"), mocker.call("baz")])
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls(
|
||||
[mocker.call("foo"), mocker.call("bar"), mocker.call("bat")]
|
||||
)
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls([mocker.call("baz"), mocker.call("bar")])
|
||||
|
||||
|
||||
def test_assert_has_calls_multiple_calls_any_order(mocker: MockerFixture) -> None:
|
||||
stub = mocker.stub()
|
||||
stub("foo")
|
||||
stub("bar")
|
||||
stub("baz")
|
||||
stub.assert_has_calls(
|
||||
[mocker.call("foo"), mocker.call("baz"), mocker.call("bar")], any_order=True
|
||||
)
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls(
|
||||
[
|
||||
mocker.call("foo"),
|
||||
mocker.call("baz"),
|
||||
mocker.call("bar"),
|
||||
mocker.call("bat"),
|
||||
],
|
||||
any_order=True,
|
||||
)
|
||||
|
||||
|
||||
def test_assert_has_calls_multiple_calls_any_order_subset(
|
||||
mocker: MockerFixture,
|
||||
) -> None:
|
||||
stub = mocker.stub()
|
||||
stub("foo")
|
||||
stub("bar")
|
||||
stub("baz")
|
||||
stub.assert_has_calls([mocker.call("baz"), mocker.call("foo")], any_order=True)
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls(
|
||||
[mocker.call("baz"), mocker.call("foo"), mocker.call("bat")], any_order=True
|
||||
)
|
||||
|
||||
|
||||
def test_assert_has_calls_no_calls(
|
||||
mocker: MockerFixture,
|
||||
) -> None:
|
||||
stub = mocker.stub()
|
||||
stub.assert_has_calls([])
|
||||
with assert_traceback():
|
||||
stub.assert_has_calls([mocker.call("foo")])
|
||||
|
||||
|
||||
def test_monkeypatch_ini(testdir: Any, mocker: MockerFixture) -> None:
|
||||
# Make sure the following function actually tests something
|
||||
stub = mocker.stub()
|
||||
|
@ -637,7 +737,6 @@ def test_monkeypatch_ini(testdir: Any, mocker: MockerFixture) -> None:
|
|||
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import py.code
|
||||
def test_foo(mocker):
|
||||
stub = mocker.stub()
|
||||
assert stub.assert_called_with.__module__ == stub.__module__
|
||||
|
@ -884,7 +983,7 @@ def test_warn_patch_object_context_manager(mocker: MockerFixture) -> None:
|
|||
"Mocks returned by pytest-mock do not need to be used as context managers. "
|
||||
"The mocker fixture automatically undoes mocking at the end of a test. "
|
||||
"This warning can be ignored if it was triggered by mocking a context manager. "
|
||||
"https://github.com/pytest-dev/pytest-mock#note-about-usage-as-context-manager"
|
||||
"https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager"
|
||||
)
|
||||
|
||||
with pytest.warns(
|
||||
|
@ -901,7 +1000,7 @@ def test_warn_patch_context_manager(mocker: MockerFixture) -> None:
|
|||
"Mocks returned by pytest-mock do not need to be used as context managers. "
|
||||
"The mocker fixture automatically undoes mocking at the end of a test. "
|
||||
"This warning can be ignored if it was triggered by mocking a context manager. "
|
||||
"https://github.com/pytest-dev/pytest-mock#note-about-usage-as-context-manager"
|
||||
"https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager"
|
||||
)
|
||||
|
||||
with pytest.warns(
|
||||
|
@ -1099,3 +1198,56 @@ def test_used_with_session_scope(testdir: Any) -> None:
|
|||
result = testdir.runpytest_subprocess()
|
||||
assert "AssertionError" not in result.stderr.str()
|
||||
result.stdout.fnmatch_lines("* 1 passed in *")
|
||||
|
||||
|
||||
def test_stop_patch(mocker):
|
||||
class UnSpy:
|
||||
def foo(self):
|
||||
return 42
|
||||
|
||||
m = mocker.patch.object(UnSpy, "foo", return_value=0)
|
||||
assert UnSpy().foo() == 0
|
||||
mocker.stop(m)
|
||||
assert UnSpy().foo() == 42
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
mocker.stop(m)
|
||||
|
||||
|
||||
def test_stop_instance_patch(mocker):
|
||||
class UnSpy:
|
||||
def foo(self):
|
||||
return 42
|
||||
|
||||
m = mocker.patch.object(UnSpy, "foo", return_value=0)
|
||||
un_spy = UnSpy()
|
||||
assert un_spy.foo() == 0
|
||||
mocker.stop(m)
|
||||
assert un_spy.foo() == 42
|
||||
|
||||
|
||||
def test_stop_spy(mocker):
|
||||
class UnSpy:
|
||||
def foo(self):
|
||||
return 42
|
||||
|
||||
spy = mocker.spy(UnSpy, "foo")
|
||||
assert UnSpy().foo() == 42
|
||||
assert spy.call_count == 1
|
||||
mocker.stop(spy)
|
||||
assert UnSpy().foo() == 42
|
||||
assert spy.call_count == 1
|
||||
|
||||
|
||||
def test_stop_instance_spy(mocker):
|
||||
class UnSpy:
|
||||
def foo(self):
|
||||
return 42
|
||||
|
||||
spy = mocker.spy(UnSpy, "foo")
|
||||
un_spy = UnSpy()
|
||||
assert un_spy.foo() == 42
|
||||
assert spy.call_count == 1
|
||||
mocker.stop(spy)
|
||||
assert un_spy.foo() == 42
|
||||
assert spy.call_count == 1
|
||||
|
|
7
tox.ini
7
tox.ini
|
@ -1,19 +1,18 @@
|
|||
[tox]
|
||||
minversion = 3.5.3
|
||||
envlist = py{37,38,39,310}, norewrite
|
||||
envlist = py{38,39,310,311,312}, norewrite
|
||||
|
||||
[testenv]
|
||||
passenv = USER USERNAME
|
||||
deps =
|
||||
coverage
|
||||
mock
|
||||
pytest-asyncio
|
||||
commands =
|
||||
coverage run --append --source={envsitepackagesdir}/pytest_mock -m pytest tests
|
||||
coverage run --append --source={envsitepackagesdir}/pytest_mock -m pytest tests --color=yes
|
||||
|
||||
[testenv:norewrite]
|
||||
commands =
|
||||
pytest tests --assert=plain
|
||||
pytest tests --assert=plain --color=yes
|
||||
|
||||
[pytest]
|
||||
addopts = -r a
|
||||
|
|
Loading…
Reference in a new issue