===================================
 Mock - Mocking and Testing Library
===================================

.. include:: ../README.rst

.. module:: mock
   :synopsis: Mock object and testing library.

.. index:: introduction

.. toctree::
   :hidden:

   changelog

Python Version Compatibility
++++++++++++++++++++++++++++

* Version 1.0.1 is the last version compatible with Python < 2.6.

* Version 1.3.0 is the last version compatible with Python 3.2.

* Version 2.0.0 is the last version compatible with Python 2.6.

* Version 2.0.0 is the last version offering official Jython support.

* version 3.0.5 is the last version supporting Python 3.5 and lower.

.. index:: installing
.. _installing:

Installing
++++++++++

.. 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``


.. index:: pip

You can install mock with pip:

    | ``pip install -U mock``

.. index:: bug reports

Bug Reports
+++++++++++

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
with Mock functionality should be reported to the `Python bug tracker
<https://bugs.python.org>`_.

.. index:: python changes

Changelog
+++++++++

See the :doc:`change log <changelog>`.

.. index:: maintainer notes

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.

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.

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``.

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
-----------------

- 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  # pragma: no cov

- If code such as this causes coverage checking to drop below 100%:

  .. code-block:: python

      def will_never_be_called():
          yield

  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():
          yield  # pragma: no cover

- If a backported patch applies cleanly, but ends up needing to be skipped,
  then commit the latest sync point and then revert the problematic commit in an immediately
  subsequent commit and make a note of the reason for the revert in that commit message.

  See `bc04ea7`__ for an example where `f4c8dc7`__ broke compatibility for all Python
  versions earlier than 3.10.

  __ https://github.com/testing-cabal/mock/commit/bc04ea76352c2064d79160f13649f879667a89cb

  __ https://github.com/testing-cabal/mock/commit/f4c8dc7098abb6b2f9a65ee86bad3891776abb50


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 ``cpython` is on ``main` and that ``main`` branch is fully up to date!
   Make sure ``mock`` is on master and up fully 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`` but not committed it,
   now would be a good time to commit that change.

Checking coverage in upstream
-----------------------------

Assuming you have the checkout structure as above, and you have compiled your cpython
master branch, then roughly as follows:

.. code-block:: bash

   ~/vcs/cpython/python.exe -m venv ~/virtualenvs/cpython-master
   source ~/virtualenvs/cpython-master/bin/activate
   pip install -U setuptools pip
   pip install pytest pytest-cov
   cd vcs/cpython/Lib/unittest
   pytest --cov unittest.mock --cov unittest.test.testmock \
          --cov-config ~/vcs/git/mock/.coveragerc \
          --cov-report term-missing:skip-covered \
          test/testmock/test*

Ignore ``test/testmock/__*__.py`` as these aren't present in the backport.
