Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions changelog/1089.deprecation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Defaulting :confval:`cache_dir` to ``$TOX_ENV_DIR/.pytest_cache`` when ``TOX_ENV_DIR`` is set in the
environment is deprecated, and will be removed in pytest 10.

It existed because ``--lf``, ``--nf`` and ``--sw`` state is not valid across interpreters, so a tox matrix
would otherwise have each environment overwrite the previous one's. pytest now keeps that state apart on
its own using :attr:`CacheScope.ENV <pytest.CacheScope.ENV>`, for every tool rather than only for tox.

Nothing needs to replace it. To keep the cache in the tox environment anyway, spell out the location that
was previously implied - :confval:`cache_dir` expands environment variables, so this is the same
expression the old default was built from::

[pytest]
cache_dir = $TOX_ENV_DIR/.pytest_cache

See :ref:`tox-env-dir-cache-dir`.
24 changes: 24 additions & 0 deletions changelog/1089.feature.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
New :confval:`cache_policy` config option, choosing *where* the cache directory lives by name rather than
by spelling out a path:

.. code-block:: ini

[pytest]
cache_policy = user

``local`` (the default) keeps the current ``<rootdir>/.pytest_cache``. ``user`` puts the cache in the
platform's user cache directory - ``$XDG_CACHE_HOME/pytest`` on Linux - under a sub-directory keyed by the
project, so nothing is written into the project at all.

The ``user`` policy requires the ``xdg`` extra: ``pip install pytest[xdg]``.

It can also be set for a whole machine with the ``PYTEST_CACHE_POLICY`` environment variable, so that
individual projects need no configuration. :confval:`cache_dir` remains an explicit path override and
always wins over the policy.

Because the interpreter in use is now distinguished by :class:`pytest.CacheScope` within a single cache
directory, one project gets one cache directory whatever runs it.

The ``cachedir:`` line in the report header now compares the resolved path against the default, so setting
:confval:`cache_dir` to ``.pytest_cache`` explicitly no longer forces the line to be shown. Where it is
shown, it is a clickable link in terminals which support hyperlinks.
20 changes: 20 additions & 0 deletions changelog/1089.feature.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
New ``--cache-list`` option, listing the cache directories under the user-level cache root together with
their size, age, origin project and the environments they hold state for:

.. code-block:: text

user cache directory: /home/ronny/.cache/pytest

DIRECTORY SIZE LAST USED STATUS ORIGIN
pytest-1a2b3c4d5e6f7a 12.4 MiB 2 days ok /home/ronny/Projects/pytest
env-venv-9f8e7d6c 1.1 MiB 2 days ok /home/ronny/Projects/pytest/.venv
env-py312-0a1b2c3d 840.1 KiB 94 days stale /home/ronny/Projects/pytest/.tox/py312
myproj-9f8e7d6c5b4a3 840 KiB 31 days orphaned /home/ronny/src/myproj

2 directories, 3 scopes, 13.2 MiB total

``orphaned`` means the project it belongs to is gone; ``stale`` means the environment a scope holds state
for is gone. Directory and origin paths are clickable in terminals which support hyperlinks.

It lists the user-level cache root regardless of the current project's :confval:`cache_policy`, so that
caches can still be found after switching back to ``local``.
15 changes: 15 additions & 0 deletions changelog/1089.feature.3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
New ``--cache-prune=SELECTOR`` option, removing cache directories or scopes under the user-level cache
root. ``SELECTOR`` is one of:

* ``all`` - every cache directory except the one this invocation would itself use;
* ``orphaned`` - directories whose project no longer exists, and directories with unreadable metadata;
* ``stale`` - *scopes* whose environment no longer exists, leaving the project's cache directory itself
in place;
* anything else - a glob, matched against the directory name and against the origin project path.

The option may be given more than once, and requires a selector: there is no default, so no bare
invocation can delete anything. Use ``--cache-list`` to preview.

Removal is not interactive, matching ``--cache-clear``. Note that nothing locks the cache, so pruning
while another pytest run is using the same cache can race; failures are reported per directory and the
command exits non-zero.
11 changes: 11 additions & 0 deletions changelog/1089.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
New :class:`pytest.CacheScope`, and a ``scope`` argument on :meth:`Cache.get <pytest.Cache.get>`,
:meth:`Cache.set <pytest.Cache.set>` and :meth:`Cache.mkdir <pytest.Cache.mkdir>`.

Cached data is not always valid everywhere a project is: last-failed test ids, for example, depend on
what the interpreter actually collects. ``scope`` lets a value be pinned to the running Python version
(:attr:`CacheScope.PYTHON <pytest.CacheScope.PYTHON>`) or environment
(:attr:`CacheScope.ENV <pytest.CacheScope.ENV>`) inside the project's single cache directory, instead of
needing a separate cache directory per environment.

The default is :attr:`CacheScope.SHARED <pytest.CacheScope.SHARED>`, which behaves exactly as before, so
existing cache directories and plugins are unaffected.
6 changes: 6 additions & 0 deletions changelog/1089.improvement.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The :fixture:`pytester` fixture now also isolates the user-level cache directory of inner test runs,
by unsetting ``XDG_CACHE_HOME`` and ``PYTEST_CACHE_HOME`` and pointing ``LOCALAPPDATA`` inside the
temporary home directory.

Previously only ``HOME``/``USERPROFILE`` were redirected, which is not enough: ``XDG_CACHE_HOME`` takes
precedence over ``HOME``, and on Windows ``LOCALAPPDATA`` is not derived from ``USERPROFILE`` at all.
9 changes: 9 additions & 0 deletions changelog/1089.improvement.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
The cache entries backing ``--lf``/``--ff``, ``--nf`` and ``--sw`` are now pinned to the environment they
were recorded in, using the new :attr:`CacheScope.ENV <pytest.CacheScope.ENV>` scope.

Running the same project under several environments - a tox or nox matrix, or simply two virtualenvs - no
longer has each run overwrite the previous one's last-failed set, without needing a separate cache
directory per environment.

Existing ``lastfailed``, ``nodeids`` and ``stepwise`` cache entries are not migrated, so the first run
after upgrading behaves as if the cache were empty.
5 changes: 5 additions & 0 deletions changelog/1089.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:class:`~_pytest.config.Config`'s terminal writer can now emit OSC 8 terminal hyperlinks, so that
paths printed by pytest are clickable in terminals which support them.

Hyperlinks are emitted only when colored output is enabled and the terminal is not known to mishandle
them. They can be forced on or off with the ``PYTEST_HYPERLINKS`` environment variable (``1`` or ``0``).
8 changes: 8 additions & 0 deletions changelog/1089.packaging.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
A new ``xdg`` extra is available: ``pip install pytest[xdg]`` pulls in platformdirs_, which pytest uses
to locate the platform's user cache directory.

The extra is only needed to store the cache outside the project directory; a plain ``pip install pytest``
is unaffected, and platformdirs is imported lazily so it is never needed otherwise. Setting
``PYTEST_CACHE_HOME`` to an explicit directory also works without the extra.

.. _platformdirs: https://pypi.org/project/platformdirs/
31 changes: 31 additions & 0 deletions doc/en/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ Below is a complete list of all pytest features which are considered deprecated.
:class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.


.. _tox-env-dir-cache-dir:

Defaulting ``cache_dir`` to ``$TOX_ENV_DIR/.pytest_cache``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 9.2

When ``TOX_ENV_DIR`` is set in the environment, :confval:`cache_dir` has defaulted to
``$TOX_ENV_DIR/.pytest_cache`` rather than to a directory inside the project. This is deprecated and
will be removed in pytest 10.

It existed because ``--lf``, ``--nf`` and ``--sw`` state is not valid across interpreters, so a tox
matrix would otherwise have each environment overwrite the previous one's. pytest now keeps that state
apart on its own, using :attr:`CacheScope.ENV <pytest.CacheScope.ENV>` within a single cache directory,
so the special case is no longer needed - and it only ever helped tox, not nox or a plain second
virtualenv.

**Nothing needs to replace it.** Once the warning is gone, the cache lands in the project like any
other, and per-environment state stays separate as it does everywhere else.

To keep the cache in the tox environment anyway, spell out the location that was previously implied:

.. code-block:: ini

[pytest]
cache_dir = $TOX_ENV_DIR/.pytest_cache

:confval:`cache_dir` expands environment variables, so this is the same expression the old default was
built from and resolves to exactly the same directory.


.. _callspec2-renamed:

``_pytest.python.CallSpec2`` renamed to ``CallSpec``
Expand Down
152 changes: 152 additions & 0 deletions doc/en/how-to/cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,158 @@ servers where isolation and correctness is more important
than speed.


.. _cache_scopes:

Cache scopes
------------

.. versionadded:: 9.2

Not everything in the cache is equally portable. Which tests exist, and which are skipped, depends on the
interpreter running them, so the state behind :option:`--lf`, :option:`--nf` and :option:`--sw <--sw>` is
only meaningful for the environment that recorded it.

pytest keeps such values apart *within* a single cache directory, rather than needing one cache directory
per environment. Every cached value has a :class:`~pytest.CacheScope`:

.. list-table::
:header-rows: 1

* - Scope
- Valid for
* - :attr:`CacheScope.SHARED <pytest.CacheScope.SHARED>`
- the project, whatever runs it. The default.
* - :attr:`CacheScope.PYTHON <pytest.CacheScope.PYTHON>`
- one Python implementation and ``major.minor`` version
* - :attr:`CacheScope.ENV <pytest.CacheScope.ENV>`
- one environment, i.e. one :data:`sys.prefix`

``--lf``, ``--nf`` and ``--sw`` use ``ENV``. Running a project under a tox or nox matrix, or simply under
two virtualenvs, therefore no longer has each run overwrite the previous one's last-failed set.

Plugins can do the same:

.. code-block:: python

def pytest_configure(config):
# Valid anywhere the project is.
config.cache.set("myplugin/schema-version", 3)

# Only valid for the environment that collected it.
config.cache.set("myplugin/collected", ids, scope=pytest.CacheScope.ENV)

Reads must use the same scope they were written with. ``SHARED`` is the default, so existing plugins keep
working and keep their existing on-disk location.


.. _cache_location:

Where the cache is stored
-------------------------

.. versionadded:: 9.2

By default the cache lives in ``.pytest_cache`` inside the :ref:`rootdir <rootdir>`. The
:confval:`cache_policy` option chooses somewhere else by name:

.. code-block:: ini

[pytest]
cache_policy = user

``local``
``<rootdir>/.pytest_cache``. The default.

``user``
A directory keyed by project inside the platform's user cache directory - ``$XDG_CACHE_HOME/pytest``
or ``~/.cache/pytest`` on Linux, ``~/Library/Caches/pytest`` on macOS, ``%LOCALAPPDATA%\pytest\Cache``
on Windows. Nothing at all is written into the project.

This requires the ``xdg`` extra::

pip install pytest[xdg]

:confval:`cache_dir` remains available and always wins: it is an explicit path, while ``cache_policy``
only chooses a location when ``cache_dir`` is unset. Use it for anywhere the two policies do not name -
it expands environment variables, so a cache inside the current virtualenv is:

.. code-block:: ini

[pytest]
cache_dir = $VIRTUAL_ENV/.pytest_cache

To opt in for a whole machine without editing every project, set the environment variable instead:

.. code-block:: bash

export PYTEST_CACHE_POLICY=user

An explicit ``cache_policy`` in a config file still wins over it.

Under the ``user`` policy the directory is named after the project and a digest of its path, so it stays
recognisable::

~/.cache/pytest/myproject-1a2b3c4d5e6f7a8b/

The key is the rootdir alone - not the interpreter, which is handled by :ref:`cache scopes <cache_scopes>`
instead. One project therefore gets one cache directory however many environments run it. A *new*
directory only appears if the project itself moves.


.. _cache_pruning:

Listing and pruning caches
--------------------------

.. versionadded:: 9.2

A cache stored inside the project is deleted along with the project. One stored under the ``user`` policy
is not, so pytest can tell you what has accumulated:

.. code-block:: bash

pytest --cache-list

.. code-block:: text

user cache directory: /home/ronny/.cache/pytest

DIRECTORY SIZE LAST USED STATUS ORIGIN
myproject-1a2b3c4d5e6f 12.4 MiB 2 days ok /home/ronny/src/myproject
env-venv-9f8e7d6c 1.1 MiB 2 days ok /home/ronny/src/myproject/.venv
env-py312-0a1b2c3d 840.1 KiB 94 days stale /home/ronny/src/myproject/.tox/py312
oldthing-9f8e7d6c5b4a 840.0 KiB 31 days orphaned /home/ronny/src/oldthing

2 directories, 3 scopes, 13.2 MiB total

``orphaned`` means the origin project no longer exists, and ``stale`` means the environment a scope holds
state for no longer exists. In terminals which support it, the directory and origin columns are clickable
links.

Nothing is ever removed automatically. To remove things, say which:

.. code-block:: bash

pytest --cache-prune=stale # state for environments that are gone
pytest --cache-prune=orphaned # caches for projects that are gone
pytest --cache-prune='oldthing-*' # by name, or by origin path
pytest --cache-prune=all

``--cache-prune`` requires a selector, so a bare invocation cannot delete anything, and it does not ask
for confirmation once given one - use ``--cache-list`` as the preview. ``all`` never removes the cache
directory of the project you run it from.

.. note::

A project on an unmounted network or removable volume looks ``orphaned``, and a virtualenv on one
looks ``stale``. This is the main reason pruning is never automatic.

.. note::

``--cache-list`` and ``--cache-prune`` only see the user-level cache root. Caches placed somewhere
else with :confval:`cache_dir` are not tracked, since pytest has no way to know where they all are.


.. _cache stepwise:

Stepwise
Expand Down
Loading
Loading