From ade10c1d65723e149e41f27da7b6d5e8edfd7493 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:51:36 +0000 Subject: [PATCH 01/22] Merge pull request #13019 from nicoddemus/release-template (#13020) Remove 'pip' command hint from release announcement (cherry picked from commit e135d760281f343cfe01c39ffa74ba920456f96d) Co-authored-by: Bruno Oliveira --- RELEASING.rst | 2 +- scripts/release.patch.rst | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/RELEASING.rst b/RELEASING.rst index 08004a84c00..033c27ac2b1 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -170,4 +170,4 @@ Both automatic and manual processes described above follow the same steps from t * python-announce-list@python.org (all releases) * testing-in-python@lists.idyll.org (only major/minor releases) - And announce it on `Twitter `_ with the ``#pytest`` hashtag. + And announce it on `Twitter `_ and `BlueSky `_ with the ``#pytest`` hashtag. diff --git a/scripts/release.patch.rst b/scripts/release.patch.rst index 59fbe50ce0e..120cae51702 100644 --- a/scripts/release.patch.rst +++ b/scripts/release.patch.rst @@ -3,9 +3,7 @@ pytest-{version} pytest {version} has just been released to PyPI. -This is a bug-fix release, being a drop-in replacement. To upgrade:: - - pip install --upgrade pytest +This is a bug-fix release, being a drop-in replacement. The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. From 179b690a724819d62f1cad6549671a753ed831b6 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:02:52 +0000 Subject: [PATCH 02/22] fix `AttributeError` crash when using `--import-mode=importlib` (#13029) (#13037) Only parent modules with the `__path__` attribute can be used by the `find_spec` function, and most of the standard library does not meet this condition. Fixes #13026 . (cherry picked from commit 8cff12865691b14b4bce70e0e304524619be385d) Co-authored-by: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> --- changelog/13026.bugfix.rst | 1 + src/_pytest/pathlib.py | 5 ++++- testing/test_pathlib.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/13026.bugfix.rst diff --git a/changelog/13026.bugfix.rst b/changelog/13026.bugfix.rst new file mode 100644 index 00000000000..d10edbd111a --- /dev/null +++ b/changelog/13026.bugfix.rst @@ -0,0 +1 @@ +Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index dd36559ce1b..a2318e79280 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -668,7 +668,10 @@ def _import_module_using_spec( parent_module: ModuleType | None = None if parent_module_name: parent_module = sys.modules.get(parent_module_name) - if parent_module is None: + # If the parent_module lacks the `__path__` attribute, AttributeError when finding a submodule's spec, + # requiring re-import according to the path. + need_reimport = not hasattr(parent_module, "__path__") + if parent_module is None or need_reimport: # Get parent_location based on location, get parent_path based on path. if module_path.name == "__init__.py": # If the current module is in a package, diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 62359303f3b..e57e031c445 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -922,6 +922,37 @@ def test_my_test(): result = pytester.runpytest("--import-mode=importlib") result.stdout.fnmatch_lines("* 1 passed *") + @pytest.mark.parametrize("name", ["code", "time", "math"]) + def test_importlib_same_name_as_stl( + self, pytester, ns_param: bool, tmp_path: Path, name: str + ): + """Import a namespace package with the same name as the standard library (#13026).""" + file_path = pytester.path / f"{name}/foo/test_demo.py" + file_path.parent.mkdir(parents=True) + file_path.write_text( + dedent( + """ + def test_demo(): + pass + """ + ), + encoding="utf-8", + ) + + # unit test + __import__(name) # import standard library + + import_path( # import user files + file_path, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=ns_param, + ) + + # E2E test + result = pytester.runpytest("--import-mode=importlib") + result.stdout.fnmatch_lines("* 1 passed *") + def create_installed_doctests_and_tests_dir( self, path: Path, monkeypatch: MonkeyPatch ) -> tuple[Path, Path, Path]: From 4e7af3572a1783f988bfa6758f6af3084c7ca54f Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:08:36 -0300 Subject: [PATCH 03/22] Fix `ImportError` crash when using `--import-mode=importlib` (#13053) (#13054) Regression in #12716 In short: `PathFinder.find_spec` received the argument `/cow/moo` but loaded `/cow/moo/moo.py` instead. **Trigger conditions:** 1. `/cow/moo/moo.py` exists (a file and directory with the same name). 2. `/cow/moo/test_moo.py` exists (test case resides in the directory). When pytest loads test files in `importlib` mode, it continues recursive loading upward: - When loading `cow.moo`, it should return a namespace but unexpectedly returns a module. - When loading `cow.moo.moo`, it should return a module but unexpectedly returns a namespace. **Complete example:** [[GitHub repository](https://github.com/dongfangtianyu/pytest_importlib_issue)](https://github.com/dongfangtianyu/pytest_importlib_issue) - `main.py`: Reproduces the error. - `debug.py`: Demonstrates the behavior of `PathFinder.find_spec`. **Context:** https://github.com/pytest-dev/pytest/issues/12592#issuecomment-2512039696 https://github.com/pytest-dev/pytest/issues/12592#issuecomment-2515100428 --------- Co-authored-by: Bruno Oliveira (cherry picked from commit 28e1e25a6782513db8a2963bd5ed5a9d66682f86) Co-authored-by: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> --- changelog/13053.bugfix.rst | 1 + src/_pytest/pathlib.py | 13 ++++++++++--- testing/test_pathlib.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelog/13053.bugfix.rst diff --git a/changelog/13053.bugfix.rst b/changelog/13053.bugfix.rst new file mode 100644 index 00000000000..b6744331394 --- /dev/null +++ b/changelog/13053.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index a2318e79280..decf8af0b4f 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -694,9 +694,16 @@ def _import_module_using_spec( # Checking with sys.meta_path first in case one of its hooks can import this module, # such as our own assertion-rewrite hook. for meta_importer in sys.meta_path: - spec = meta_importer.find_spec( - module_name, [str(module_location), str(module_path)] - ) + module_name_of_meta = getattr(meta_importer.__class__, "__module__", "") + if module_name_of_meta == "_pytest.assertion.rewrite" and module_path.is_file(): + # Import modules in subdirectories by module_path + # to ensure assertion rewrites are not missed (#12659). + find_spec_path = [str(module_location), str(module_path)] + else: + find_spec_path = [str(module_location)] + + spec = meta_importer.find_spec(module_name, find_spec_path) + if spec_matches_module_path(spec, module_path): break else: diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index e57e031c445..1acc96915d4 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1498,6 +1498,34 @@ def test(): ] ) + def test_ns_multiple_levels_import_error( + self, + tmp_path: Path, + pytester: Pytester, + ) -> None: + # Trigger condition 1: ns and file with the same name + file = pytester.path / "cow/moo/moo.py" + file.parent.mkdir(parents=True) + file.write_text("data=123", encoding="utf-8") + + # Trigger condition 2: tests are located in ns + tests = pytester.path / "cow/moo/test_moo.py" + + tests.write_text( + dedent( + """ + from cow.moo.moo import data + + def test_moo(): + print(data) + """ + ), + encoding="utf-8", + ) + + result = pytester.runpytest("--import-mode=importlib") + assert result.ret == ExitCode.OK + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) def test_incorrect_namespace_package( self, From 544bf20d4394901ba80d4fd790a3003977626b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 16 Dec 2024 06:02:44 +0100 Subject: [PATCH 04/22] Merge pull request #13064 from pytest-dev/dependabot/github_actions/pypa/gh-action-pypi-publish-1.12.3 build(deps): Bump pypa/gh-action-pypi-publish from 1.12.2 to 1.12.3 (cherry picked from commit d5254b50f8c1302e86a4fc81780ca513cdf2fb24) --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6238a6fedcc..7f4381e7f61 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.2 + uses: pypa/gh-action-pypi-publish@v1.12.3 with: attestations: true From e4d842ac5deae61773961f94d8b2b401b34802ad Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 16 Dec 2024 12:18:31 +0200 Subject: [PATCH 05/22] [8.3.x] ci: fix failing jobs due to pluggy requiring Python>=3.9 Some of the pluggy jobs (I guess the ones fetching from git) started to fail since pluggy dropped support for 3.8 and the jobs are running with 3.8. So bump them to 3.9. --- .github/workflows/test.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3131f487ab9..687807faf9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,7 +55,7 @@ jobs: matrix: name: [ "windows-py38", - "windows-py38-pluggy", + "windows-py39-pluggy", "windows-py39", "windows-py310", "windows-py311", @@ -63,7 +63,7 @@ jobs: "windows-py313", "ubuntu-py38", - "ubuntu-py38-pluggy", + "ubuntu-py39-pluggy", "ubuntu-py38-freeze", "ubuntu-py39", "ubuntu-py310", @@ -88,10 +88,10 @@ jobs: os: windows-latest tox_env: "py38-unittestextras" use_coverage: true - - name: "windows-py38-pluggy" - python: "3.8" + - name: "windows-py39-pluggy" + python: "3.9" os: windows-latest - tox_env: "py38-pluggymain-pylib-xdist" + tox_env: "py39-pluggymain-pylib-xdist" - name: "windows-py39" python: "3.9" os: windows-latest @@ -118,10 +118,10 @@ jobs: os: ubuntu-latest tox_env: "py38-lsof-numpy-pexpect" use_coverage: true - - name: "ubuntu-py38-pluggy" - python: "3.8" + - name: "ubuntu-py39-pluggy" + python: "3.9" os: ubuntu-latest - tox_env: "py38-pluggymain-pylib-xdist" + tox_env: "py39-pluggymain-pylib-xdist" - name: "ubuntu-py38-freeze" python: "3.8" os: ubuntu-latest @@ -192,9 +192,9 @@ jobs: contains( fromJSON( '[ - "windows-py38-pluggy", + "windows-py39-pluggy", "windows-py313", - "ubuntu-py38-pluggy", + "ubuntu-py39-pluggy", "ubuntu-py38-freeze", "ubuntu-py313", "macos-py38", From c2abd05a8801c617c6d3204bdc9c447e6ed32bbd Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:15:40 +0000 Subject: [PATCH 06/22] ci: harden github actions according to "zizmor" recommendations (#13062) (#13067) Fix all issues reported by zizmor 0.9.2 running locally. See: https://woodruffw.github.io/zizmor/ (cherry picked from commit ee8f98d2f976a1df17093eab12e00f0f3c4bee29) Co-authored-by: Ran Benita --- .github/workflows/deploy.yml | 12 +++++++++--- .github/workflows/prepare-release-pr.yml | 11 +++++++++-- .github/workflows/update-plugin-list.yml | 6 ++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7f4381e7f61..7613f41fbb5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -46,6 +46,8 @@ jobs: contents: write steps: - uses: actions/checkout@v4 + with: + persist-credentials: true - name: Download Package uses: actions/download-artifact@v4 @@ -59,11 +61,13 @@ jobs: attestations: true - name: Push tag + env: + VERSION: ${{ github.event.inputs.version }} run: | git config user.name "pytest bot" git config user.email "pytestbot@gmail.com" - git tag --annotate --message=v${{ github.event.inputs.version }} ${{ github.event.inputs.version }} ${{ github.sha }} - git push origin ${{ github.event.inputs.version }} + git tag --annotate --message=v"$VERSION" "$VERSION" ${{ github.sha }} + git push origin "$VERSION" release-notes: @@ -98,9 +102,11 @@ jobs: pip install --upgrade tox - name: Generate release notes + env: + VERSION: ${{ github.event.inputs.version }} run: | sudo apt-get install pandoc - tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md + tox -e generate-gh-release-notes -- "$VERSION" scripts/latest-release-notes.md - name: Publish GitHub Release uses: softprops/action-gh-release@v2 diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index 1bb23fab844..fdb770317df 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -30,6 +30,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + persist-credentials: false - name: Set up Python uses: actions/setup-python@v5 @@ -43,10 +44,16 @@ jobs: - name: Prepare release PR (minor/patch release) if: github.event.inputs.major == 'no' + env: + BRANCH: ${{ github.event.inputs.branch }} + PRERELEASE: ${{ github.event.inputs.prerelease }} run: | - tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --prerelease='${{ github.event.inputs.prerelease }}' + tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --prerelease="$PRERELEASE" - name: Prepare release PR (major release) if: github.event.inputs.major == 'yes' + env: + BRANCH: ${{ github.event.inputs.branch }} + PRERELEASE: ${{ github.event.inputs.prerelease }} run: | - tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --major --prerelease='${{ github.event.inputs.prerelease }}' + tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --major --prerelease="$PRERELEASE" diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index ade8452afd5..267ed69396e 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -23,12 +23,14 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + persist-credentials: false - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip + - name: requests-cache uses: actions/cache@v4 with: @@ -41,7 +43,6 @@ jobs: python -m pip install --upgrade pip pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs - - name: Update Plugin List run: python scripts/update-plugin-list.py @@ -61,8 +62,9 @@ jobs: - name: Instruct the maintainers to trigger CI by undrafting the PR env: GITHUB_TOKEN: ${{ github.token }} + PULL_REQUEST_NUMBER: ${{ steps.pr.outputs.pull-request-number }} run: >- gh pr comment --body 'Please mark the PR as ready for review to trigger PR checks.' --repo '${{ github.repository }}' - '${{ steps.pr.outputs.pull-request-number }}' + "$PULL_REQUEST_NUMBER" From 763a1aab9fbf6e35554b8d18de5678499dbc680a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 16 Dec 2024 22:20:06 +0100 Subject: [PATCH 07/22] Merge pull request #13069 from bluetech/zizmor-pre-commit pre-commit: add zizmor hook (cherry picked from commit 76a7f59a90e078a498253f68cb6d26d39cc17d5b) --- .pre-commit-config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7806f68e2d8..1a8469a2f04 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,10 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml +- repo: https://github.com/woodruffw/zizmor-pre-commit + rev: v0.9.2 + hooks: + - id: zizmor - repo: https://github.com/adamchainz/blacken-docs rev: 1.18.0 hooks: From ad4081f63985ff42f54fc52baa7ce0e7b5cffba4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 8 Jan 2025 18:04:15 +0100 Subject: [PATCH 08/22] Merge pull request #13113 from The-Compiler/fix-pygments-whitespace Fix selftests with Pygments >= 2.19.0 (cherry picked from commit bdfc3a99bd733f385f150446caef6d5843bb6418) --- changelog/13112.contrib.rst | 1 + testing/conftest.py | 7 +++++++ testing/test_terminal.py | 10 +++++----- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelog/13112.contrib.rst diff --git a/changelog/13112.contrib.rst b/changelog/13112.contrib.rst new file mode 100644 index 00000000000..5e59a736edb --- /dev/null +++ b/changelog/13112.contrib.rst @@ -0,0 +1 @@ +Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 diff --git a/testing/conftest.py b/testing/conftest.py index 69af03324d6..194da0f8309 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -2,10 +2,13 @@ from __future__ import annotations import dataclasses +import importlib.metadata import re import sys from typing import Generator +from packaging.version import Version + from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester import pytest @@ -168,6 +171,9 @@ def color_mapping(): Used by tests which check the actual colors output by pytest. """ + # https://github.com/pygments/pygments/commit/d24e272894a56a98b1b718d9ac5fabc20124882a + pygments_version = Version(importlib.metadata.version("pygments")) + pygments_has_kwspace_hl = pygments_version >= Version("2.19") class ColorMapping: COLORS = { @@ -180,6 +186,7 @@ class ColorMapping: "bold": "\x1b[1m", "reset": "\x1b[0m", "kw": "\x1b[94m", + "kwspace": "\x1b[90m \x1b[39;49;00m" if pygments_has_kwspace_hl else " ", "hl-reset": "\x1b[39;49;00m", "function": "\x1b[92m", "number": "\x1b[94m", diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 14c152d6123..cbbe9cbd7a9 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1299,13 +1299,13 @@ def test_this(): "=*= FAILURES =*=", "{red}{bold}_*_ test_this _*_{reset}", "", - " {reset}{kw}def{hl-reset} {function}test_this{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_this{hl-reset}():{endline}", "> fail(){endline}", "", "{bold}{red}test_color_yes.py{reset}:5: ", "_ _ * _ _*", "", - " {reset}{kw}def{hl-reset} {function}fail{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}fail{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", "", @@ -2585,7 +2585,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] @@ -2607,7 +2607,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", " {print}print{hl-reset}({str}'''{hl-reset}{str}{hl-reset}", "> {str} {hl-reset}{str}'''{hl-reset}); {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", @@ -2630,7 +2630,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] From f1c6bab42d696b0d2c5158038c5c891b6c7f8e69 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 18:29:39 -0300 Subject: [PATCH 09/22] Fix crash when directory is removed during collection (#13086) (#13117) Fixes #13083 --------- Co-authored-by: Bruno Oliveira (cherry picked from commit 3214263b2f0d17b265c40cf5f87d70357b9a219d) Co-authored-by: delta87 <124760624+delta87@users.noreply.github.com> --- AUTHORS | 1 + changelog/13083.bugfix.rst | 1 + src/_pytest/pathlib.py | 13 ++++++++++--- testing/test_pathlib.py | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 changelog/13083.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e25156cde19..deb42adbe30 100644 --- a/AUTHORS +++ b/AUTHORS @@ -353,6 +353,7 @@ Ran Benita Raphael Castaneda Raphael Pierzina Rafal Semik +Reza Mousavi Raquel Alegre Ravi Chandra Reagan Lee diff --git a/changelog/13083.bugfix.rst b/changelog/13083.bugfix.rst new file mode 100644 index 00000000000..fc4564755ba --- /dev/null +++ b/changelog/13083.bugfix.rst @@ -0,0 +1 @@ +Fixed issue where pytest could crash if one of the collected directories got removed during collection. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index decf8af0b4f..ca8a1d2d4f9 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -955,17 +955,24 @@ def scandir( The returned entries are sorted according to the given key. The default is to sort by name. + If the directory does not exist, return an empty list. """ entries = [] - with os.scandir(path) as s: - # Skip entries with symlink loops and other brokenness, so the caller - # doesn't have to deal with it. + # Attempt to create a scandir iterator for the given path. + try: + scandir_iter = os.scandir(path) + except FileNotFoundError: + # If the directory does not exist, return an empty list. + return [] + # Use the scandir iterator in a context manager to ensure it is properly closed. + with scandir_iter as s: for entry in s: try: entry.is_file() except OSError as err: if _ignore_error(err): continue + # Reraise non-ignorable errors to avoid hiding issues. raise entries.append(entry) entries.sort(key=sort_key) # type: ignore[arg-type] diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 1acc96915d4..dbf76887859 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -38,6 +38,7 @@ from _pytest.pathlib import resolve_package_path from _pytest.pathlib import resolve_pkg_root_and_module_name from _pytest.pathlib import safe_exists +from _pytest.pathlib import scandir from _pytest.pathlib import spec_matches_module_path from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit @@ -569,6 +570,29 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N assert getattr(module, "foo")() == 42 +def test_scandir_with_non_existent_directory() -> None: + # Test with a directory that does not exist + non_existent_dir = "path_to_non_existent_dir" + result = scandir(non_existent_dir) + # Assert that the result is an empty list + assert result == [] + + +def test_scandir_handles_os_error() -> None: + # Create a mock entry that will raise an OSError when is_file is called + mock_entry = unittest.mock.MagicMock() + mock_entry.is_file.side_effect = OSError("some permission error") + # Mock os.scandir to return an iterator with our mock entry + with unittest.mock.patch("os.scandir") as mock_scandir: + mock_scandir.return_value.__enter__.return_value = [mock_entry] + # Call the scandir function with a path + # We expect an OSError to be raised here + with pytest.raises(OSError, match="some permission error"): + scandir("/fake/path") + # Verify that the is_file method was called on the mock entry + mock_entry.is_file.assert_called_once() + + class TestImportLibMode: def test_importmode_importlib_with_dataclass( self, tmp_path: Path, ns_param: bool From 02519fdf2386db733adb238c17aa8459f2e7a5df Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:48:20 -0300 Subject: [PATCH 10/22] Update links to microblogging pages (#13123) (#13127) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update links to microblogging pages * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) (cherry picked from commit 05538acf906d6f6e0f75d1d0e2e2052e933761de) Co-authored-by: Florian Bruhin --- RELEASING.rst | 6 +++++- doc/en/contact.rst | 7 +++++++ pyproject.toml | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/RELEASING.rst b/RELEASING.rst index 033c27ac2b1..000eae814d3 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -170,4 +170,8 @@ Both automatic and manual processes described above follow the same steps from t * python-announce-list@python.org (all releases) * testing-in-python@lists.idyll.org (only major/minor releases) - And announce it on `Twitter `_ and `BlueSky `_ with the ``#pytest`` hashtag. + And announce it with the ``#pytest`` hashtag on: + + * `Bluesky `_ + * `Fosstodon `_ + * `Twitter/X `_ diff --git a/doc/en/contact.rst b/doc/en/contact.rst index d650a7efbab..cd34f548e99 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -24,6 +24,13 @@ Chat `_) - ``#pytest`` `on Matrix `_. +Microblogging +------------- + +- Bluesky: `@pytest.org `_ +- Mastodon: `@pytest@fosstodon.org `_ +- Twitter/X: `@pytestdotorg `_ + Mail ---- diff --git a/pyproject.toml b/pyproject.toml index c7941f9dafa..ff27906537a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,10 +64,11 @@ optional-dependencies.dev = [ "xmlschema", ] urls.Changelog = "https://docs.pytest.org/en/stable/changelog.html" +urls.Contact = "https://docs.pytest.org/en/stable/contact.html" +urls.Funding = "https://docs.pytest.org/en/stable/sponsor.html" urls.Homepage = "https://docs.pytest.org/en/latest/" urls.Source = "https://github.com/pytest-dev/pytest" urls.Tracker = "https://github.com/pytest-dev/pytest/issues" -urls.Twitter = "https://twitter.com/pytestdotorg" scripts."py.test" = "pytest:console_main" scripts.pytest = "pytest:console_main" From ef06e438e50994381bc235a60d59b946732619d5 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:27:12 +0000 Subject: [PATCH 11/22] Fix example in pytest_collection_modifyitems (#13152) (#13154) Ref #13149 (cherry picked from commit 4a6a512443e5e1aaed0b5bb0cc82adb2c09d4b66) Co-authored-by: Bruno Oliveira --- src/_pytest/hookspec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 0a41b0aca47..ed843606fea 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -277,7 +277,7 @@ def pytest_collection_modifyitems( When items are deselected (filtered out from ``items``), the hook :hook:`pytest_deselected` must be called explicitly with the deselected items to properly notify other plugins, - e.g. with ``config.hook.pytest_deselected(deselected_items)``. + e.g. with ``config.hook.pytest_deselected(items=deselected_items)``. :param session: The pytest session object. :param config: The pytest config object. From 4dbec99454cf9fc1282e77fa6ca607939d710abe Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 26 Jan 2025 10:15:35 -0300 Subject: [PATCH 12/22] Fix sequences being shortened even with `-vv` verbosity. (#13163) Fix #11777 Co-authored-by: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> --- changelog/11777.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 3 +++ testing/test_terminal.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 changelog/11777.bugfix.rst diff --git a/changelog/11777.bugfix.rst b/changelog/11777.bugfix.rst new file mode 100644 index 00000000000..3f1ffc27a68 --- /dev/null +++ b/changelog/11777.bugfix.rst @@ -0,0 +1 @@ +Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 37c09b03467..1f11935c70e 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -28,6 +28,7 @@ from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr +from _pytest._io.saferepr import saferepr_unlimited from _pytest._version import version from _pytest.assertion import util from _pytest.config import Config @@ -432,6 +433,8 @@ def _saferepr(obj: object) -> str: return obj.__name__ maxsize = _get_maxsize_for_saferepr(util._config) + if not maxsize: + return saferepr_unlimited(obj).replace("\n", "\\n") return saferepr(obj, maxsize=maxsize).replace("\n", "\\n") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index cbbe9cbd7a9..14125560d5a 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2525,6 +2525,35 @@ def test(): ) +def test_full_sequence_print_with_vv( + monkeypatch: MonkeyPatch, pytester: Pytester +) -> None: + """Do not truncate sequences in summaries with -vv (#11777).""" + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + pytester.makepyfile( + """ + def test_len_list(): + l = list(range(10)) + assert len(l) == 9 + + def test_len_dict(): + d = dict(zip(range(10), range(10))) + assert len(d) == 9 + """ + ) + + result = pytester.runpytest("-vv") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*short test summary info*", + f"*{list(range(10))}*", + f"*{dict(zip(range(10), range(10)))}*", + ] + ) + + @pytest.mark.parametrize( "seconds, expected", [ From 8728b1afebd02ba0aa0aadeb38815f18adac1d28 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:48:21 +0100 Subject: [PATCH 13/22] Update pythonpath.rst (#13181) (#13182) Fix two tiny typos in `pythonpath.rst` (cherry picked from commit c962c86845aea805f47c33f1c67582640a7d3e6f) Co-authored-by: Sadra Barikbin --- doc/en/explanation/pythonpath.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index d0314a6dbcd..e68f455cedf 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -8,7 +8,7 @@ pytest import mechanisms and ``sys.path``/``PYTHONPATH`` Import modes ------------ -pytest as a testing framework that needs to import test modules and ``conftest.py`` files for execution. +pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution. Importing files in Python is a non-trivial process, so aspects of the import process can be controlled through the ``--import-mode`` command-line flag, which can assume @@ -78,7 +78,7 @@ these values: For non-test modules, this will work if they are accessible via :py:data:`sys.path`. So for example, ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. - This is happens when plugins import non-test modules (for example doctesting). + This happens when plugins import non-test modules (for example doctesting). If this step succeeds, the module is returned. From 78cf1f67f707fc07372a89775fd10d2065b5f17a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 3 Feb 2025 23:20:39 +0100 Subject: [PATCH 14/22] ci: Bump build-and-inspect-python-package (#13188) Otherwise the build is broken as Python 3.13 is used, but the pinned pydantic-core version doesn't have support. --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7613f41fbb5..9dc69c3cca3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.6.0 + uses: hynek/build-and-inspect-python-package@v2.12.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 687807faf9a..33dede68906 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.6.0 + uses: hynek/build-and-inspect-python-package@v2.12.0 build: needs: [package] From eb6496b79759f9acde581ed9d7a0777a49b5f820 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 16:09:37 +0000 Subject: [PATCH 15/22] doc: Change training to remote only (#13196) (#13197) (cherry picked from commit 1f1a10c0da051ada2cbb04d1592d0e14f6de1ac6) Co-authored-by: Florian Bruhin --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 8b34d589643..7f3dbdd800d 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Remote Also see :doc:`previous talks and blogposts ` From 2ebba0063c66b77a7bd171221de059f3b3e47b86 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 08:03:12 -0300 Subject: [PATCH 16/22] Merge pull request #13199 from jakkdl/tox_docs_no_fetch (#13200) remove `git fetch` from tox `docs` environment (cherry picked from commit de1a4885d6fd27e4189aba94b8922acc58364142) Co-authored-by: John Litborn <11260241+jakkdl@users.noreply.github.com> --- tox.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tox.ini b/tox.ini index 61563ca2c5f..1a6ab344de8 100644 --- a/tox.ini +++ b/tox.ini @@ -104,13 +104,7 @@ basepython = python3.12 # sync with rtd to get errors usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt -allowlist_externals = - git commands = - # Retrieve possibly missing commits: - -git fetch --unshallow - -git fetch --tags - sphinx-build \ -j auto \ -W --keep-going \ From edbfff72a4051ed9c5f3d9b5d6f316b407cb6961 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 15 Feb 2025 15:09:53 +0000 Subject: [PATCH 17/22] doc: Clarify capturing .readouterr() return value (#13222) (#13225) This got added in 38fb6aae7830837209c40ec1a4ccb68950bc107c, where the "The return value ... changed" made a lot of sense. However, 9c5da9c0d15ccf7ab9f3a8fbd6540e4a56ea789f removed the "versionadded" without adjusting the wording. Also see 3a4435fb59604d40c5d2e2f65e9acba99dd9cff0. (cherry picked from commit 62aa4272229a4e604582db534796df1a729b4752) Co-authored-by: Florian Bruhin --- doc/en/how-to/capture-stdout-stderr.rst | 2 +- doc/en/how-to/parametrize.rst | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 9f7ddce3499..d91bef736e7 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -131,7 +131,7 @@ test from having to care about setting/resetting output streams and also interacts well with pytest's own per-test capturing. -The return value from ``readouterr`` changed to a ``namedtuple`` with two attributes, ``out`` and ``err``. +The return value of ``readouterr()`` is a ``namedtuple`` with two attributes, ``out`` and ``err``. If the code under test writes non-textual data (``bytes``), you can capture this using the :fixture:`capsysbinary` fixture which instead returns ``bytes`` from diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index b6466c491b4..5a16684eb96 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -29,10 +29,6 @@ pytest enables test parametrization at several levels: .. regendoc: wipe - - - Several improvements. - The builtin :ref:`pytest.mark.parametrize ref` decorator enables parametrization of arguments for a test function. Here is a typical example of a test function that implements checking that a certain input leads From b75cfb162dbb927739698effa3fbcf279655da49 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 3 Feb 2025 14:46:28 +0100 Subject: [PATCH 18/22] Add readline workaround for libedit (#13176) * Add readline workaround for libedit We had a very similar workaround before for pyreadline, which had a similar issue: - Introduced in #1281 - Removed in #8848 for #8733 and #8847 This technically will regress the issues above, but those issues just mean that `import readline` is broken in general, so the user should fix it instead (by e.g. uninstalling pyreadline). Fixes #12888 Fixes #13170 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Handle no readline on Windows --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> (cherry picked from commit b4009b31978053fe077a32d219ad947a5ba7243c) --- changelog/12888.bugfix.rst | 1 + src/_pytest/capture.py | 18 ++++++++++++++++++ testing/test_capture.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 changelog/12888.bugfix.rst diff --git a/changelog/12888.bugfix.rst b/changelog/12888.bugfix.rst new file mode 100644 index 00000000000..635e35a11ea --- /dev/null +++ b/changelog/12888.bugfix.rst @@ -0,0 +1 @@ +Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 506c0b3d287..ded8af87fd9 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -79,6 +79,23 @@ def _colorama_workaround() -> None: pass +def _readline_workaround() -> None: + """Ensure readline is imported early so it attaches to the correct stdio handles. + + This isn't a problem with the default GNU readline implementation, but in + some configurations, Python uses libedit instead (on macOS, and for prebuilt + binaries such as used by uv). + + In theory this is only needed if readline.backend == "libedit", but the + workaround consists of importing readline here, so we already worked around + the issue by the time we could check if we need to. + """ + try: + import readline # noqa: F401 + except ImportError: + pass + + def _windowsconsoleio_workaround(stream: TextIO) -> None: """Workaround for Windows Unicode console handling. @@ -140,6 +157,7 @@ def pytest_load_initial_conftests(early_config: Config) -> Generator[None]: if ns.capture == "fd": _windowsconsoleio_workaround(sys.stdout) _colorama_workaround() + _readline_workaround() pluginmanager = early_config.pluginmanager capman = CaptureManager(ns.capture) pluginmanager.register(capman, "capturemanager") diff --git a/testing/test_capture.py b/testing/test_capture.py index 328de740e8a..adf1c3b2657 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -5,6 +5,7 @@ import io from io import UnsupportedOperation import os +import re import subprocess import sys import textwrap @@ -1666,3 +1667,32 @@ def test_logging(): ) result.stdout.no_fnmatch_line("*Captured stderr call*") result.stdout.no_fnmatch_line("*during collection*") + + +def test_libedit_workaround(pytester: Pytester) -> None: + pytester.makeconftest(""" + import pytest + + + def pytest_terminal_summary(config): + capture = config.pluginmanager.getplugin("capturemanager") + capture.suspend_global_capture(in_=True) + + print("Enter 'hi'") + value = input() + print(f"value: {value!r}") + + capture.resume_global_capture() + """) + readline = pytest.importorskip("readline") + backend = getattr(readline, "backend", readline.__doc__) # added in Python 3.13 + print(f"Readline backend: {backend}") + + child = pytester.spawn_pytest("") + child.expect(r"Enter 'hi'") + child.sendline("hi") + rest = child.read().decode("utf8") + print(rest) + match = re.search(r"^value: '(.*)'\r?$", rest, re.MULTILINE) + assert match is not None + assert match.group(1) == "hi" From e5c2efe3c36199731b41fd68bbf4df5e21404a8b Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 13:59:48 +0000 Subject: [PATCH 19/22] Merge pull request #13256 from webknjaz/maintenance/towncrier-bump (#13258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit c4028e90bbd2007a9054de66dedda61f358b568a) Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- changelog/13256.contrib.rst | 2 ++ doc/en/broken-dep-constraints.txt | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) create mode 100644 changelog/13256.contrib.rst diff --git a/changelog/13256.contrib.rst b/changelog/13256.contrib.rst new file mode 100644 index 00000000000..fe3bac87ca1 --- /dev/null +++ b/changelog/13256.contrib.rst @@ -0,0 +1,2 @@ +Support for Towncier versions released in 2024 has been re-enabled +when building Sphinx docs -- by :user:`webknjaz`. diff --git a/doc/en/broken-dep-constraints.txt b/doc/en/broken-dep-constraints.txt index 3a8d2c34b5a..1488e06fa23 100644 --- a/doc/en/broken-dep-constraints.txt +++ b/doc/en/broken-dep-constraints.txt @@ -1,6 +1,2 @@ # This file contains transitive dependencies that need to be pinned for some reason. # Eventually this file will be empty, but in this case keep it around for future use. - -# Pin towncrier temporarily due to incompatibility with sphinxcontrib-towncrier: -# https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 -towncrier<24.7 From 2fa3f8306c3da4aad7f7349a4947ac37ba6c652f Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 14:45:35 +0000 Subject: [PATCH 20/22] Add more resources and studies to flaky tests page in docs (#13250) (#13259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) Co-authored-by: Bruno Oliveira (cherry picked from commit 9f3c4d11d9b162d0926e9a3ae57ec6f262362d73) Co-authored-by: Vincent (Wen Yu) Ge --- doc/en/explanation/flaky.rst | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index cb6c3983424..8369e1d9311 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -117,8 +117,11 @@ This is a limited list, please submit an issue or pull request to expand it! * Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon, and Zhen Wang. "Making system user interactive tests repeatable: When and what should we control?." In *Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on*, vol. 1, pp. 55-65. IEEE, 2015. `PDF `__ * Palomba, Fabio, and Andy Zaidman. "Does refactoring of test smells induce fixing flaky tests?." In *Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on*, pp. 1-12. IEEE, 2017. `PDF in Google Drive `__ -* Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: Automatically detecting flaky tests." In *Proceedings of the 2018 International Conference on Software Engineering*. 2018. `PDF `__ -* Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "Detecting flaky tests in probabilistic and machine learning applications." In *Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA)*, pp. 211-224. ACM, 2020. `PDF `__ +* Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: Automatically detecting flaky tests." In *Proceedings of the 2018 International Conference on Software Engineering*. 2018. `PDF `__ +* Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "Detecting flaky tests in probabilistic and machine learning applications." In *Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA)*, pp. 211-224. ACM, 2020. `PDF `__ +* Habchi, Sarra and Haben, Guillaume and Sohn, Jeongju and Franci, Adriano and Papadakis, Mike and Cordy, Maxime and Le Traon, Yves. "What Made This Test Flake? Pinpointing Classes Responsible for Test Flakiness." In Proceedings of the 38th IEEE International Conference on Software Maintenance and Evolution (ICSME), IEEE, 2022. `PDF `__ +* Lamprou, Sokrates. "Non-deterministic tests and where to find them: Empirically investigating the relationship between flaky tests and test smells by examining test order dependency." Bachelor thesis, Department of Computer and Information Science, Linköping University, 2022. LIU-IDA/LITH-EX-G–19/056–SE. `PDF `__ +* Leinen, Fabian and Elsner, Daniel and Pretschner, Alexander and Stahlbauer, Andreas and Sailer, Michael and Jürgens, Elmar. "Cost of Flaky Tests in Continuous Integration: An Industrial Case Study." Technical University of Munich and CQSE GmbH, Munich, Germany, 2023. `PDF `__ Resources ^^^^^^^^^ @@ -137,5 +140,12 @@ Resources * `Flaky Tests at Google and How We Mitigate Them `_ by John Micco, 2016 * `Where do Google's flaky tests come from? `_ by Jeff Listfield, 2017 +* Dropbox: + * `Athena: Our automated build health management system `_ by Utsav Shah, 2019 + * `How To Manage Flaky Tests in your CI Workflows `_ by Li Haoyi, 2025 + +* Uber: + * `Handling Flaky Unit Tests in Java `_ by Uber Engineering, 2021 + * `Flaky Tests Overhaul at Uber `_ by Uber Engineering, 2024 .. _pytest-xdist: https://github.com/pytest-dev/pytest-xdist From e217726d2a0edfaf58eae95bf835b85834b96da3 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 16:17:22 +0000 Subject: [PATCH 21/22] Added dedicated page about using types with pytest #12842 (#12963) (#13260) Fixes #12842 --------- Co-authored-by: Bruno Oliveira (cherry picked from commit ca351458d85d0276ee4aa3079c8305feafe42b76) Co-authored-by: mwychung <145583690+mwychung@users.noreply.github.com> --- AUTHORS | 1 + changelog/12842.doc.rst | 3 ++ doc/en/explanation/index.rst | 1 + doc/en/explanation/types.rst | 89 ++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 changelog/12842.doc.rst create mode 100644 doc/en/explanation/types.rst diff --git a/AUTHORS b/AUTHORS index deb42adbe30..e8ae5e4beaa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -255,6 +255,7 @@ lovetheguitar Lukas Bednar Luke Murphy Maciek Fijalkowski +Maggie Chung Maho Maik Figura Mandeep Bhutani diff --git a/changelog/12842.doc.rst b/changelog/12842.doc.rst new file mode 100644 index 00000000000..0a0f5c5bc23 --- /dev/null +++ b/changelog/12842.doc.rst @@ -0,0 +1,3 @@ +Added dedicated page about using types with pytest. + +See :ref:`types` for detailed usage. diff --git a/doc/en/explanation/index.rst b/doc/en/explanation/index.rst index 2edf60a5d8b..2606d7d4b34 100644 --- a/doc/en/explanation/index.rst +++ b/doc/en/explanation/index.rst @@ -12,5 +12,6 @@ Explanation fixtures goodpractices pythonpath + types ci flaky diff --git a/doc/en/explanation/types.rst b/doc/en/explanation/types.rst new file mode 100644 index 00000000000..827a2bf02b6 --- /dev/null +++ b/doc/en/explanation/types.rst @@ -0,0 +1,89 @@ +.. _types: + +Typing in pytest +================ + +.. note:: + This page assumes the reader is familiar with Python's typing system and its advantages. + + For more information, refer to `Python's Typing Documentation `_. + +Why type tests? +--------------- + +Typing tests provides significant advantages: + +- **Readability:** Clearly defines expected inputs and outputs, improving readability, especially in complex or parameterized tests. + +- **Refactoring:** This is the main benefit in typing tests, as it will greatly help with refactoring, letting the type checker point out the necessary changes in both production and tests, without needing to run the full test suite. + +For production code, typing also helps catching some bugs that might not be caught by tests at all (regardless of coverage), for example: + +.. code-block:: python + + def get_caption(target: int, items: list[tuple[int, str]]) -> str: + for value, caption in items: + if value == target: + return caption + + +The type checker will correctly error out that the function might return `None`, however even a full coverage test suite might miss that case: + +.. code-block:: python + + def test_get_caption() -> None: + assert get_caption(10, [(1, "foo"), (10, "bar")]) == "bar" + + +Note the code above has 100% coverage, but the bug is not caught (of course the example is "obvious", but serves to illustrate the point). + + + +Using typing in test suites +--------------------------- + +To type fixtures in pytest, just add normal types to the fixture functions -- there is nothing special that needs to be done just because of the `fixture` decorator. + +.. code-block:: python + + import pytest + + + @pytest.fixture + def sample_fixture() -> int: + return 38 + +In the same manner, the fixtures passed to test functions need be annotated with the fixture's return type: + +.. code-block:: python + + def test_sample_fixture(sample_fixture: int) -> None: + assert sample_fixture == 38 + +From the POV of the type checker, it does not matter that `sample_fixture` is actually a fixture managed by pytest, all it matters to it is that `sample_fixture` is a parameter of type `int`. + + +The same logic applies to :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>`: + +.. code-block:: python + + + @pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (10, 11)]) + def test_increment(input_value: int, expected_output: int) -> None: + assert input_value + 1 == expected_output + + +The same logic applies when typing fixture functions which receive other fixtures: + +.. code-block:: python + + @pytest.fixture + def mock_env_user(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("USER", "TestingUser") + + +Conclusion +---------- + +Incorporating typing into pytest tests enhances **clarity**, improves **debugging** and **maintenance**, and ensures **type safety**. +These practices lead to a **robust**, **readable**, and **easily maintainable** test suite that is better equipped to handle future changes with minimal risk of errors. From b55ab2aabb68c0ce94c3903139b062d0c2790152 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 2 Mar 2025 12:47:09 +0000 Subject: [PATCH 22/22] Prepare release version 8.3.5 --- changelog/11777.bugfix.rst | 1 - changelog/12842.doc.rst | 3 --- changelog/12888.bugfix.rst | 1 - changelog/13026.bugfix.rst | 1 - changelog/13053.bugfix.rst | 1 - changelog/13083.bugfix.rst | 1 - changelog/13112.contrib.rst | 1 - changelog/13256.contrib.rst | 2 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.3.5.rst | 26 ++++++++++++++++++ doc/en/builtin.rst | 8 +++--- doc/en/changelog.rst | 41 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 15 ++++++----- doc/en/example/pythoncollection.rst | 4 +-- doc/en/example/reportingdemo.rst | 18 ++++++------- doc/en/example/simple.rst | 2 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/reference/reference.rst | 14 +++++----- 19 files changed, 102 insertions(+), 42 deletions(-) delete mode 100644 changelog/11777.bugfix.rst delete mode 100644 changelog/12842.doc.rst delete mode 100644 changelog/12888.bugfix.rst delete mode 100644 changelog/13026.bugfix.rst delete mode 100644 changelog/13053.bugfix.rst delete mode 100644 changelog/13083.bugfix.rst delete mode 100644 changelog/13112.contrib.rst delete mode 100644 changelog/13256.contrib.rst create mode 100644 doc/en/announce/release-8.3.5.rst diff --git a/changelog/11777.bugfix.rst b/changelog/11777.bugfix.rst deleted file mode 100644 index 3f1ffc27a68..00000000000 --- a/changelog/11777.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. diff --git a/changelog/12842.doc.rst b/changelog/12842.doc.rst deleted file mode 100644 index 0a0f5c5bc23..00000000000 --- a/changelog/12842.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added dedicated page about using types with pytest. - -See :ref:`types` for detailed usage. diff --git a/changelog/12888.bugfix.rst b/changelog/12888.bugfix.rst deleted file mode 100644 index 635e35a11ea..00000000000 --- a/changelog/12888.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. diff --git a/changelog/13026.bugfix.rst b/changelog/13026.bugfix.rst deleted file mode 100644 index d10edbd111a..00000000000 --- a/changelog/13026.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. diff --git a/changelog/13053.bugfix.rst b/changelog/13053.bugfix.rst deleted file mode 100644 index b6744331394..00000000000 --- a/changelog/13053.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` diff --git a/changelog/13083.bugfix.rst b/changelog/13083.bugfix.rst deleted file mode 100644 index fc4564755ba..00000000000 --- a/changelog/13083.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed issue where pytest could crash if one of the collected directories got removed during collection. diff --git a/changelog/13112.contrib.rst b/changelog/13112.contrib.rst deleted file mode 100644 index 5e59a736edb..00000000000 --- a/changelog/13112.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 diff --git a/changelog/13256.contrib.rst b/changelog/13256.contrib.rst deleted file mode 100644 index fe3bac87ca1..00000000000 --- a/changelog/13256.contrib.rst +++ /dev/null @@ -1,2 +0,0 @@ -Support for Towncier versions released in 2024 has been re-enabled -when building Sphinx docs -- by :user:`webknjaz`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 8a38df7a2e1..51edc964a0c 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.3.5 release-8.3.4 release-8.3.3 release-8.3.2 diff --git a/doc/en/announce/release-8.3.5.rst b/doc/en/announce/release-8.3.5.rst new file mode 100644 index 00000000000..3de02c1d7a4 --- /dev/null +++ b/doc/en/announce/release-8.3.5.rst @@ -0,0 +1,26 @@ +pytest-8.3.5 +======================================= + +pytest 8.3.5 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Florian Bruhin +* John Litborn +* Kenny Y +* Ran Benita +* Sadra Barikbin +* Vincent (Wen Yu) Ge +* delta87 +* dongfangtianyu +* mwychung +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 85d280da50f..8aa6fef681c 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1006 + capsysbinary -- .../_pytest/capture.py:1024 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -51,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1034 + capfd -- .../_pytest/capture.py:1052 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1062 + capfdbinary -- .../_pytest/capture.py:1080 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -87,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:978 + capsys -- .../_pytest/capture.py:996 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index a01c2589f1f..c95ba561969 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,47 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.5 (2025-03-02) +========================= + +Bug fixes +--------- + +- `#11777 `_: Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. + + +- `#12888 `_: Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. + + +- `#13026 `_: Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. + + +- `#13053 `_: Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` + + +- `#13083 `_: Fixed issue where pytest could crash if one of the collected directories got removed during collection. + + + +Improved documentation +---------------------- + +- `#12842 `_: Added dedicated page about using types with pytest. + + See :ref:`types` for detailed usage. + + + +Contributor-facing changes +-------------------------- + +- `#13112 `_: Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 + + +- `#13256 `_: Support for Towncier versions released in 2024 has been re-enabled + when building Sphinx docs -- by :user:`webknjaz`. + + pytest 8.3.4 (2024-12-01) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index f1f7deb909c..69e715c9db1 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + @@ -503,11 +503,12 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - ssssssssssss...ssssssssssss [100%] + sssssssssssssssssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [12] multipython.py:67: 'python3.9' not found - SKIPPED [12] multipython.py:67: 'python3.11' not found - 3 passed, 24 skipped in 0.12s + SKIPPED [9] multipython.py:67: 'python3.9' not found + SKIPPED [9] multipython.py:67: 'python3.10' not found + SKIPPED [9] multipython.py:67: 'python3.11' not found + 27 skipped in 0.12s Parametrization of optional implementations/imports --------------------------------------------------- diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 1d1ce07c10a..89d7ee42614 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 0da58d0490e..5e48815bbc9 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -568,12 +568,12 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where False = ('456') E + where = '123'.startswith E + where '123' = .f at 0xdeadbeef0029>() - E + and '456' = .g at 0xdeadbeef002a>() + E + and '456' = .g at 0xdeadbeef0003>() failure_demo.py:237: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -584,18 +584,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:240: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:244: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -605,7 +605,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:247: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -616,7 +616,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:252: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -631,7 +631,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:263: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -650,7 +650,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:270: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index a14c34c19c3..bc6c2784849 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -164,7 +164,7 @@ Now we'll get feedback on a bad argument: $ pytest -q --cmdopt=type3 ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] - pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from 'type1', 'type2') + pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from type1, type2) If you need to provide more detailed error messages, you can use the diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index d4308e5aab3..5b9f38d7bf7 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.4 + pytest 8.3.5 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 9232c9e8449..8f84e4867a6 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 31cf363100a..5035353fb49 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1988,7 +1988,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: Show cache contents, don't perform collection or tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run - --lfnf={all,none}, --last-failed-no-failures={all,none} + --lfnf, --last-failed-no-failures={all,none} With ``--lf``, determines whether to execute tests when there are no previously (known) failures or when no cached ``lastfailed`` data was found. @@ -2034,11 +2034,13 @@ All the command-line flags can be obtained by running ``pytest --help``:: Whether code should be highlighted (only if --color is also enabled). Default: yes. --pastebin=mode Send failed|all info to bpaste.net pastebin service - --junit-xml=path Create junit-xml style report file at given path - --junit-prefix=str Prepend prefix to classnames in junit-xml output + --junitxml, --junit-xml=path + Create junit-xml style report file at given path + --junitprefix, --junit-prefix=str + Prepend prefix to classnames in junit-xml output pytest-warnings: - -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS + -W, --pythonwarnings PYTHONWARNINGS Set which warnings to report, see -W option of Python itself --maxfail=num Exit after first num failures or errors @@ -2047,7 +2049,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: --strict-markers Markers not registered in the `markers` section of the configuration file raise errors --strict (Deprecated) alias to --strict-markers - -c FILE, --config-file=FILE + -c, --config-file FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors @@ -2101,7 +2103,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: Store internal tracing debug information in this log file. This file is opened with 'w' and truncated as a result, care advised. Default: pytestdebug.log. - -o OVERRIDE_INI, --override-ini=OVERRIDE_INI + -o, --override-ini OVERRIDE_INI Override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools.