Skip to content
Merged
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
35 changes: 35 additions & 0 deletions .github/actions/setup-tox/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Set up tox
description: >
Install uv and tox with the tox-uv plugin using the official
`uv tool install tox --with tox-uv` pattern.

inputs:
python-version:
description: >
Python version for `uv tool install --python`. When omitted, uv uses the
interpreter already available on PATH (for example from actions/setup-python).
required: false
default: ""
enable-cache:
description: Enable the uv cache via astral-sh/setup-uv.
required: false
default: "true"

runs:
using: composite
steps:
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: ${{ inputs.enable-cache }}

- name: Install tox
shell: bash
env:
PYTHON_VERSION: ${{ inputs.python-version }}
run: |
if [ -n "$PYTHON_VERSION" ]; then
uv tool install --python "$PYTHON_VERSION" tox --with tox-uv
else
uv tool install tox --with tox-uv
fi
9 changes: 2 additions & 7 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,11 @@ jobs:
fetch-depth: 0
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- name: Set up tox
uses: ./.github/actions/setup-tox
with:
python-version: "3.13"

- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox

- name: Generate release notes
env:
VERSION: ${{ github.event.inputs.version }}
Expand Down
10 changes: 2 additions & 8 deletions .github/workflows/doc-check-links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,10 @@ jobs:
fetch-depth: 0
persist-credentials: false

- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- name: Set up tox
uses: ./.github/actions/setup-tox
with:
python-version: "3.13"
cache: pip

- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox

- name: Run sphinx linkcheck via tox
run: tox -e docs-checklinks
9 changes: 2 additions & 7 deletions .github/workflows/prepare-release-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,11 @@ jobs:
# persist-credentials is needed in order for us to push the release branch.
persist-credentials: true

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- name: Set up tox
uses: ./.github/actions/setup-tox
with:
python-version: "3.13"

- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox

- name: Prepare release PR (minor/patch release)
if: github.event.inputs.major == 'no'
env:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,10 @@ jobs:
check-latest: true
allow-prereleases: true

- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: Set up tox
uses: ./.github/actions/setup-tox
with:
python-version: ${{ matrix.python }}

- name: Test without coverage
if: "! matrix.use_coverage"
Expand Down
13 changes: 4 additions & 9 deletions .github/workflows/update-plugin-list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,17 @@ jobs:
fetch-depth: 0
persist-credentials: false

- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"

- name: requests-cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/pytest-plugin-list/
key: plugins-http-cache-${{ github.run_id }} # Can use time based key as well
restore-keys: plugins-http-cache-

- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: Set up tox
uses: ./.github/actions/setup-tox
with:
python-version: "3.13"

- name: Update Plugin List
run: tox -e update-plugin-list
Expand Down
10 changes: 7 additions & 3 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,17 @@ Here is a simple overview, with pytest-specific bits:

When committing, ``pre-commit`` will re-format the files if necessary.

#. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use
an editable install with the ``dev`` extra::
#. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and
install the project together with the ``dev`` :pep:`735` dependency group (requires ``pip`` 25.1+)::

$ python3 -m venv .venv
$ source .venv/bin/activate # Linux
$ .venv/Scripts/activate.bat # Windows
$ pip install -e ".[dev]"
$ pip install -e . --group dev

Alternatively, with ``uv``::

$ uv sync --group dev

Afterwards, you can edit the files and run pytest normally::

Expand Down
38 changes: 31 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,29 @@ dynamic = [
dependencies = [
"colorama>=0.4; sys_platform=='win32'",
"exceptiongroup>=1; python_version<'3.11'",
"iniconfig>=1.0.1",
"packaging>=22",
"iniconfig>=2",
"packaging>=24",
"pluggy>=1.5,<2",
"pygments>=2.7.2",
"tomli>=1; python_version<'3.11'",
"pygments>=2.15",
"tomli>=2; python_version<'3.11'",
]
# Kept as a published extra because many external repos still install
# `pytest[dev]` / `.[dev]`. Prefer the `dev` dependency group for local
# development of pytest itself (see CONTRIBUTING.rst).
optional-dependencies.dev = [
# Core test dependencies
"argcomplete",
"attrs>=19.2",
"hypothesis>=3.56",
"asynctest; python_version<'3.11'",
"attrs>=23.1",
# Test execution and coverage
"coverage>=7.5",
"hypothesis>=6.75",
"mock",
"numpy>=1.26",
"pexpect>=4.9",
"pytest-xdist>=3.5",
# Additional test dependencies
"pyyaml",
"requests",
"setuptools",
"xmlschema",
Expand All @@ -73,6 +85,12 @@ urls.Tracker = "https://github.com/pytest-dev/pytest/issues"
scripts."py.test" = "_pytest.config:_console_main"
scripts.pytest = "_pytest.config:_console_main"

[dependency-groups]
# Preferred entry point for developing pytest; pulls from optional-dependencies.dev.
dev = [
"pytest[dev]",
]

[tool.setuptools.package-data]
"_pytest" = [
"py.typed",
Expand Down Expand Up @@ -418,7 +436,13 @@ filterwarnings = [
# https://github.com/pytest-dev/pytest/pull/13057
'default::pytest.PytestFDWarning',
# https://github.com/pexpect/pexpect/issues/827
'ignore:.*use of forkpty\(\) may lead to deadlocks in the child:DeprecationWarning:ptyprocess.*',
# CPython emits this from os.forkpty() with stacklevel=1, so it is attributed
# to stdlib pty (caller of os.forkpty via pty.fork), not ptyprocess. Match on
# message only: module attribution must not be required if stacklevel changes.
# Becomes a hard failure under filterwarnings=error only on 3.15+
# (python/cpython#136796 stopped clearing the warning). Often seen on macOS
# because Mach task_threads counts extra runtime threads.
'ignore:.*use of forkpty\(\) may lead to deadlocks in the child:DeprecationWarning',
]
pytester_example_dir = "testing/example_scripts"
markers = [
Expand Down
5 changes: 5 additions & 0 deletions testing/test_debugging.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def pdb_env(request):
# Disable pdb++ with inner tests.
pytester = request.getfixturevalue("pytester")
pytester._monkeypatch.setenv("PDBPP_HIJACK_PDB", "0")
# Python 3.15+ defaults pdb to PyREPL, which injects ANSI colors and
# bracketed-paste sequences into pexpect output and breaks exact
# matching in these selftests. Force the classic REPL instead.
# https://docs.python.org/3.15/whatsnew/3.15.html#pdb
pytester._monkeypatch.setenv("PYTHON_BASIC_REPL", "1")


def runpdb(pytester: Pytester, source: str):
Expand Down
29 changes: 17 additions & 12 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[tox]
requires =
tox >= 4
tox-uv >= 1.25
envlist =
linting
py310
Expand Down Expand Up @@ -98,19 +99,13 @@ setenv =
lsof: _PYTEST_TOX_POSARGS_LSOF=--lsof

xdist: _PYTEST_TOX_POSARGS_XDIST=-n auto
extras = dev
dependency_groups = dev
deps =
coverage: coverage>=7.10
doctesting: PyYAML
exceptiongroup: exceptiongroup>=1.0.0rc8
numpy: numpy>=1.19.4
pexpect: pexpect>=4.8.0
exceptiongroup: exceptiongroup>=1.2
pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git
pylib: py>=1.8.2
pylib: py>=1.11
twisted24: twisted<25
twisted25: twisted>=25
asynctest: asynctest
xdist: pytest-xdist>=2.1.0
# Can use the same wheel for all environments.
package = wheel
wheel_build_env = .pkg
Expand All @@ -119,7 +114,8 @@ wheel_build_env = .pkg
description =
run pre-commit-defined linters under `{basepython}`
skip_install = True
deps = pre-commit>=2.9.3
dependency_groups =
deps = pre-commit>=4
commands = pre-commit run --all-files --show-diff-on-failure {posargs:}
setenv =
# pre-commit and tools it launches are not clean of this warning.
Expand All @@ -131,6 +127,7 @@ description =
`{toxinidir}{/}doc{/}en{/}_build{/}html` with `{basepython}`
basepython = python3.14 # Sync with .readthedocs.yaml to get errors.
usedevelop = True
dependency_groups =
deps =
-r{toxinidir}/doc/en/requirements.txt
commands =
Expand All @@ -148,6 +145,7 @@ description =
check the links in the documentation with `{basepython}`
usedevelop = True
changedir = doc/en
dependency_groups =
deps = -r{toxinidir}/doc/en/requirements.txt
commands =
sphinx-build -W -q --keep-going -b linkcheck . _build
Expand All @@ -159,6 +157,7 @@ setenv =
description =
regenerate documentation examples under `{basepython}`
changedir = doc/en
dependency_groups =
deps =
PyYAML
regendoc>=0.8.1
Expand All @@ -181,12 +180,13 @@ description =
# use latest versions of all plugins, including pre-releases
pip_pre=true
changedir = testing/plugins_integration
dependency_groups =
deps = -rtesting/plugins_integration/requirements.txt
allowlist_externals = pip
allowlist_externals = uv
setenv =
PYTHONPATH=.
commands =
pip check
uv pip check
pytest bdd_wallet.py
pytest --cov=. simple_integration.py
pytest --ds=django_settings simple_integration.py
Expand All @@ -203,6 +203,7 @@ commands =
description =
test pytest frozen with `pyinstaller` under `{basepython}`
changedir = testing/freeze
dependency_groups =
deps =
pyinstaller
commands =
Expand All @@ -213,6 +214,7 @@ commands =
description = do a release, required posarg of the version number
usedevelop = True
passenv = *
dependency_groups =
deps =
colorama
pre-commit>=2.9.3
Expand All @@ -223,19 +225,22 @@ commands = python scripts/release.py {posargs}
description = prepare a release PR from a manual trigger in GitHub actions
usedevelop = {[testenv:release]usedevelop}
passenv = {[testenv:release]passenv}
dependency_groups = {[testenv:release]dependency_groups}
deps = {[testenv:release]deps}
commands = python scripts/prepare-release-pr.py {posargs}

[testenv:generate-gh-release-notes]
description = generate release notes that can be published as GitHub Release
usedevelop = True
dependency_groups =
deps =
pypandoc_binary
commands = python scripts/generate-gh-release-notes.py {posargs}

[testenv:update-plugin-list]
description = update the plugin list
skip_install = True
dependency_groups =
deps =
packaging
requests
Expand Down
Loading
Loading