From 26b0702b9834acf01f3bd2d2354fc0be797b7546 Mon Sep 17 00:00:00 2001 From: Vijay Arora Date: Fri, 1 Oct 2021 19:34:59 +0530 Subject: [PATCH 001/157] Updated logging.py Updated logging.py for #9146 --- src/_pytest/logging.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 7f73b8a4685..29cb4c75102 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -447,7 +447,10 @@ def clear(self) -> None: self.handler.reset() def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: - """Set the level of a logger for the duration of a test. + """Sets the threshold for this logger to level. Logging messages which are less + severe than level will be ignored; logging messages which have severity level or + higher will be emitted by whichever handler or handlers service this logger, unless + a handler’s level has been set to a higher severity level than level. .. versionchanged:: 3.4 The levels of the loggers changed by this function will be From a8697601ad36436caaa3af63ed3803424059c8fc Mon Sep 17 00:00:00 2001 From: Vijay Arora Date: Fri, 1 Oct 2021 20:10:46 +0530 Subject: [PATCH 002/157] Create 9146.doc.rst Create 9146.doc.rst --- changelog/9146.doc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/9146.doc.rst diff --git a/changelog/9146.doc.rst b/changelog/9146.doc.rst new file mode 100644 index 00000000000..77b375e899f --- /dev/null +++ b/changelog/9146.doc.rst @@ -0,0 +1 @@ +Documentation improvement for #9146 From 307dbf15c42ca5f3e104b600250426b011a3bce3 Mon Sep 17 00:00:00 2001 From: Vijay Arora Date: Fri, 1 Oct 2021 20:16:10 +0530 Subject: [PATCH 003/157] Add Myself as Authors --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index bfc2d3e46ee..1ee61d65efe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -328,6 +328,7 @@ Vasily Kuznetsov Victor Maryama Victor Uriarte Vidar T. Fauske +Vijay Arora Virgil Dupras Vitaly Lashmanov Vlad Dragos From de1f378b60e9e5c0e4f0ab4eb873ddc1f1d236b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 14:53:25 +0000 Subject: [PATCH 004/157] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/logging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 29cb4c75102..3f2d03059a0 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -447,8 +447,8 @@ def clear(self) -> None: self.handler.reset() def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: - """Sets the threshold for this logger to level. Logging messages which are less - severe than level will be ignored; logging messages which have severity level or + """Sets the threshold for this logger to level. Logging messages which are less + severe than level will be ignored; logging messages which have severity level or higher will be emitted by whichever handler or handlers service this logger, unless a handler’s level has been set to a higher severity level than level. From 750ce30392b1d0b99d3172e8e28aa946b1b24975 Mon Sep 17 00:00:00 2001 From: Vijay Arora Date: Fri, 1 Oct 2021 21:33:32 +0530 Subject: [PATCH 005/157] Update 9146.doc.rst --- changelog/9146.doc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/9146.doc.rst b/changelog/9146.doc.rst index 77b375e899f..95189b96d46 100644 --- a/changelog/9146.doc.rst +++ b/changelog/9146.doc.rst @@ -1 +1 @@ -Documentation improvement for #9146 +Improve Documentation for `caplog.set_level`. From 5fefd7de96d26f61a60bcdb54785f2ceb170f57a Mon Sep 17 00:00:00 2001 From: Vijay Arora Date: Fri, 1 Oct 2021 21:36:35 +0530 Subject: [PATCH 006/157] Updated indentation and spaces in logging.py for #9146 --- src/_pytest/logging.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 3f2d03059a0..9267c4070a9 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -447,10 +447,12 @@ def clear(self) -> None: self.handler.reset() def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: - """Sets the threshold for this logger to level. Logging messages which are less - severe than level will be ignored; logging messages which have severity level or - higher will be emitted by whichever handler or handlers service this logger, unless - a handler’s level has been set to a higher severity level than level. + """Sets the threshold for this logger to level. + + Logging messages which are less severe than level will be ignored; logging messages + which have severity level or higher will be emitted by whichever handler or handlers + service this logger, unless a handler’s level has been set to a higher severity level + than `level`. .. versionchanged:: 3.4 The levels of the loggers changed by this function will be From bb6155adfa52cae6f77f239f0a1915854ee565cf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 16:07:38 +0000 Subject: [PATCH 007/157] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/logging.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 9267c4070a9..92a0cb6c639 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -447,11 +447,11 @@ def clear(self) -> None: self.handler.reset() def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: - """Sets the threshold for this logger to level. - - Logging messages which are less severe than level will be ignored; logging messages - which have severity level or higher will be emitted by whichever handler or handlers - service this logger, unless a handler’s level has been set to a higher severity level + """Sets the threshold for this logger to level. + + Logging messages which are less severe than level will be ignored; logging messages + which have severity level or higher will be emitted by whichever handler or handlers + service this logger, unless a handler’s level has been set to a higher severity level than `level`. .. versionchanged:: 3.4 From f1c75851846c5b709049fa92d609b4736b72474b Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Fri, 31 Mar 2023 10:00:45 -0700 Subject: [PATCH 008/157] Update fixture scope in package/directory fixture example. --- doc/en/example/simple.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index fa3e68ce94a..97a6dd9f436 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -691,7 +691,7 @@ Here is an example for making a ``db`` fixture available in a directory: pass - @pytest.fixture(scope="session") + @pytest.fixture(scope="package") def db(): return DB() From 2d2dc4a2a8eb40d1d04c2f5673734ea958efb5cc Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Apr 2023 00:18:07 +0300 Subject: [PATCH 009/157] tox: remove `dataclasses` dependency from `regen` This dep is not needed on newer Pythons. --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index 663ada60caf..88ae16dea0c 100644 --- a/tox.ini +++ b/tox.ini @@ -100,7 +100,6 @@ basepython = python3 passenv = SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST deps = - dataclasses PyYAML regendoc>=0.8.1 sphinx From bf47357511c6f13012e89f7e142c8c6b4bf413c0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Apr 2023 00:49:26 +0300 Subject: [PATCH 010/157] Merge pull request #10881 from pytest-dev/release-7.3.0 Prepare release 7.3.0 (cherry picked from commit cec5bfe0588adaa2ca36c72c724378982db6410a) --- changelog/10226.improvement.rst | 1 - changelog/10525.feature.rst | 1 - changelog/10658.improvement.rst | 3 - changelog/10669.trivial.rst | 1 - changelog/10710.improvement.rst | 1 - changelog/10727.improvement.rst | 1 - changelog/10743.bugfix.rst | 1 - changelog/10755.feature.rst | 1 - changelog/10765.bugfix.rst | 1 - changelog/10782.doc.rst | 1 - changelog/10840.improvement.rst | 1 - changelog/1904.bugfix.rst | 1 - changelog/6267.improvement.rst | 2 - changelog/7431.feature.rst | 1 - changelog/8141.feature.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.3.0.rst | 130 ++++++++++++++++++++++++++++++ doc/en/changelog.rst | 70 ++++++++++++++++ doc/en/example/parametrize.rst | 8 +- doc/en/example/reportingdemo.rst | 102 +++++++++++------------ doc/en/getting-started.rst | 2 +- 21 files changed, 259 insertions(+), 72 deletions(-) delete mode 100644 changelog/10226.improvement.rst delete mode 100644 changelog/10525.feature.rst delete mode 100644 changelog/10658.improvement.rst delete mode 100644 changelog/10669.trivial.rst delete mode 100644 changelog/10710.improvement.rst delete mode 100644 changelog/10727.improvement.rst delete mode 100644 changelog/10743.bugfix.rst delete mode 100644 changelog/10755.feature.rst delete mode 100644 changelog/10765.bugfix.rst delete mode 100644 changelog/10782.doc.rst delete mode 100644 changelog/10840.improvement.rst delete mode 100644 changelog/1904.bugfix.rst delete mode 100644 changelog/6267.improvement.rst delete mode 100644 changelog/7431.feature.rst delete mode 100644 changelog/8141.feature.rst create mode 100644 doc/en/announce/release-7.3.0.rst diff --git a/changelog/10226.improvement.rst b/changelog/10226.improvement.rst deleted file mode 100644 index f1506eaf79e..00000000000 --- a/changelog/10226.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -If multiple errors are raised in teardown, we now re-raise an ``ExceptionGroup`` of them instead of discarding all but the last. diff --git a/changelog/10525.feature.rst b/changelog/10525.feature.rst deleted file mode 100644 index 15652b0246d..00000000000 --- a/changelog/10525.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Test methods decorated with ``@classmethod`` can now be discovered as tests, following the same rules as normal methods. This fills the gap that static methods were discoverable as tests but not class methods. diff --git a/changelog/10658.improvement.rst b/changelog/10658.improvement.rst deleted file mode 100644 index 54e5ae84f24..00000000000 --- a/changelog/10658.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allow ``-p`` arguments to include spaces (eg: ``-p no:logging`` instead of -``-pno:logging``). Mostly useful in the ``addopts`` section of the configuration -file. diff --git a/changelog/10669.trivial.rst b/changelog/10669.trivial.rst deleted file mode 100644 index 6cebe12ec26..00000000000 --- a/changelog/10669.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -pytest no longer depends on the `attrs` package (don't worry, nice diffs for attrs classes are still supported). diff --git a/changelog/10710.improvement.rst b/changelog/10710.improvement.rst deleted file mode 100644 index a893eec0257..00000000000 --- a/changelog/10710.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added ``start`` and ``stop`` timestamps to ``TestReport`` objects. diff --git a/changelog/10727.improvement.rst b/changelog/10727.improvement.rst deleted file mode 100644 index 92cb8cc33a6..00000000000 --- a/changelog/10727.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Split the report header for ``rootdir``, ``config file`` and ``testpaths`` so each has its own line. diff --git a/changelog/10743.bugfix.rst b/changelog/10743.bugfix.rst deleted file mode 100644 index ad5c63e80ee..00000000000 --- a/changelog/10743.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -The assertion rewriting mechanism now works correctly when assertion expressions contain the walrus operator. diff --git a/changelog/10755.feature.rst b/changelog/10755.feature.rst deleted file mode 100644 index 5fb5a97d4ac..00000000000 --- a/changelog/10755.feature.rst +++ /dev/null @@ -1 +0,0 @@ -:confval:`console_output_style` now supports ``progress-even-when-capture-no`` to force the use of the progress output even when capture is disabled. This is useful in large test suites where capture may have significant performance impact. diff --git a/changelog/10765.bugfix.rst b/changelog/10765.bugfix.rst deleted file mode 100644 index 89391f1f0cd..00000000000 --- a/changelog/10765.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :fixture:`tmp_path` fixture always raising :class:`OSError` on ``emscripten`` platform due to missing :func:`os.getuid`. diff --git a/changelog/10782.doc.rst b/changelog/10782.doc.rst deleted file mode 100644 index c2bd4af8c31..00000000000 --- a/changelog/10782.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the minimal example in :ref:`goodpractices`: ``pip install -e .`` requires a ``version`` entry in ``pyproject.toml`` to run successfully. diff --git a/changelog/10840.improvement.rst b/changelog/10840.improvement.rst deleted file mode 100644 index 17be0d07b06..00000000000 --- a/changelog/10840.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -pytest should no longer crash on AST with pathological position attributes, for example testing AST produced by `Hylang __`. diff --git a/changelog/1904.bugfix.rst b/changelog/1904.bugfix.rst deleted file mode 100644 index dc8e0f34217..00000000000 --- a/changelog/1904.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Correctly handle ``__tracebackhide__`` for chained exceptions. diff --git a/changelog/6267.improvement.rst b/changelog/6267.improvement.rst deleted file mode 100644 index ed551cecc33..00000000000 --- a/changelog/6267.improvement.rst +++ /dev/null @@ -1,2 +0,0 @@ -The full output of a test is no longer truncated if the truncation message would be longer than -the hidden text. The line number shown has also been fixed. diff --git a/changelog/7431.feature.rst b/changelog/7431.feature.rst deleted file mode 100644 index 24a64a2ae37..00000000000 --- a/changelog/7431.feature.rst +++ /dev/null @@ -1 +0,0 @@ -``--log-disable`` CLI option added to disable individual loggers. diff --git a/changelog/8141.feature.rst b/changelog/8141.feature.rst deleted file mode 100644 index b589ed2e98b..00000000000 --- a/changelog/8141.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy` configuration options to control how directories created by the :fixture:`tmp_path` fixture are kept. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index fa57ca5c8af..96db2e248a7 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.3.0 release-7.2.2 release-7.2.1 release-7.2.0 diff --git a/doc/en/announce/release-7.3.0.rst b/doc/en/announce/release-7.3.0.rst new file mode 100644 index 00000000000..33258dabade --- /dev/null +++ b/doc/en/announce/release-7.3.0.rst @@ -0,0 +1,130 @@ +pytest-7.3.0 +======================================= + +The pytest team is proud to announce the 7.3.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Aaron Berdy +* Adam Turner +* Albert Villanova del Moral +* Alessio Izzo +* Alex Hadley +* Alice Purcell +* Anthony Sottile +* Anton Yakutovich +* Ashish Kurmi +* Babak Keyvani +* Billy +* Brandon Chinn +* Bruno Oliveira +* Cal Jacobson +* Chanvin Xiao +* Cheuk Ting Ho +* Chris Wheeler +* Daniel Garcia Moreno +* Daniel Scheffler +* Daniel Valenzuela +* EmptyRabbit +* Ezio Melotti +* Felix Hofstätter +* Florian Best +* Florian Bruhin +* Fredrik Berndtsson +* Gabriel Landau +* Garvit Shubham +* Gergely Kalmár +* HTRafal +* Hugo van Kemenade +* Ilya Konstantinov +* Itxaso Aizpurua +* James Gerity +* Jay +* John Litborn +* Jon Parise +* Jouke Witteveen +* Kadino +* Kevin C +* Kian Eliasi +* Klaus Rettinghaus +* Kodi Arfer +* Mahesh Vashishtha +* Manuel Jacob +* Marko Pacak +* MatthewFlamm +* Miro Hrončok +* Nate Meyvis +* Neil Girdhar +* Nhieuvu1802 +* Nipunn Koorapati +* Ofek Lev +* Paul Kehrer +* Paul Müller +* Paul Reece +* Pax +* Pete Baughman +* Peyman Salehi +* Philipp A +* Pierre Sassoulas +* Prerak Patel +* Ramsey +* Ran Benita +* Robert O'Shea +* Ronny Pfannschmidt +* Rowin +* Ruth Comer +* Samuel Colvin +* Samuel Gaist +* Sandro Tosi +* Santiago Castro +* Shantanu +* Simon K +* Stefanie Molin +* Stephen Rosen +* Sviatoslav Sydorenko +* Tatiana Ovary +* Teejay +* Thierry Moisan +* Thomas Grainger +* Tim Hoffmann +* Tobias Diez +* Tony Narlock +* Vivaan Verma +* Wolfremium +* Yannick PÉROUX +* Yusuke Kadowaki +* Zac Hatfield-Dodds +* Zach OBrien +* aizpurua23a +* bitzge +* bluthej +* gresm +* holesch +* itxasos23 +* johnkangw +* q0w +* rdb +* s-padmanaban +* skhomuti +* sommersoft +* vin01 +* wim glenn +* wodny +* zx.qiu + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 020e6289e48..4fc959c6b19 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,76 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.3.0 (2023-04-08) +========================= + +Features +-------- + +- `#10525 `_: Test methods decorated with ``@classmethod`` can now be discovered as tests, following the same rules as normal methods. This fills the gap that static methods were discoverable as tests but not class methods. + + +- `#10755 `_: :confval:`console_output_style` now supports ``progress-even-when-capture-no`` to force the use of the progress output even when capture is disabled. This is useful in large test suites where capture may have significant performance impact. + + +- `#7431 `_: ``--log-disable`` CLI option added to disable individual loggers. + + +- `#8141 `_: Added :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy` configuration options to control how directories created by the :fixture:`tmp_path` fixture are kept. + + + +Improvements +------------ + +- `#10226 `_: If multiple errors are raised in teardown, we now re-raise an ``ExceptionGroup`` of them instead of discarding all but the last. + + +- `#10658 `_: Allow ``-p`` arguments to include spaces (eg: ``-p no:logging`` instead of + ``-pno:logging``). Mostly useful in the ``addopts`` section of the configuration + file. + + +- `#10710 `_: Added ``start`` and ``stop`` timestamps to ``TestReport`` objects. + + +- `#10727 `_: Split the report header for ``rootdir``, ``config file`` and ``testpaths`` so each has its own line. + + +- `#10840 `_: pytest should no longer crash on AST with pathological position attributes, for example testing AST produced by `Hylang __`. + + +- `#6267 `_: The full output of a test is no longer truncated if the truncation message would be longer than + the hidden text. The line number shown has also been fixed. + + + +Bug Fixes +--------- + +- `#10743 `_: The assertion rewriting mechanism now works correctly when assertion expressions contain the walrus operator. + + +- `#10765 `_: Fixed :fixture:`tmp_path` fixture always raising :class:`OSError` on ``emscripten`` platform due to missing :func:`os.getuid`. + + +- `#1904 `_: Correctly handle ``__tracebackhide__`` for chained exceptions. + + + +Improved Documentation +---------------------- + +- `#10782 `_: Fixed the minimal example in :ref:`goodpractices`: ``pip install -e .`` requires a ``version`` entry in ``pyproject.toml`` to run successfully. + + + +Trivial/Internal Changes +------------------------ + +- `#10669 `_: pytest no longer depends on the `attrs` package (don't worry, nice diffs for attrs classes are still supported). + + pytest 7.2.2 (2023-03-03) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 1b25dfaf72a..df2859b14e0 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -502,8 +502,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 - ........................... [100%] - 27 passed in 0.12s + sssssssssssssssssssssssssss [100%] + ========================= short test summary info ========================== + SKIPPED [9] multipython.py:69: 'python3.5' not found + SKIPPED [9] multipython.py:69: 'python3.6' not found + SKIPPED [9] multipython.py:69: 'python3.7' not found + 27 skipped in 0.12s Indirect parametrization of optional implementations/imports -------------------------------------------------------------------- diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 20dc0a019f2..cb59c4b42e1 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -70,12 +70,12 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert not f() E assert not 42 - E + where 42 = .f at 0xdeadbeef0002>() + E + where 42 = .f at 0xdeadbeef0006>() failure_demo.py:39: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ - self = + self = def test_eq_text(self): > assert "spam" == "eggs" @@ -86,7 +86,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:44: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ - self = + self = def test_eq_similar_text(self): > assert "foo 1 bar" == "foo 2 bar" @@ -99,7 +99,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:47: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ - self = + self = def test_eq_multiline_text(self): > assert "foo\nspam\nbar" == "foo\neggs\nbar" @@ -112,7 +112,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:50: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ - self = + self = def test_eq_long_text(self): a = "1" * 100 + "a" + "2" * 100 @@ -129,7 +129,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:55: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ - self = + self = def test_eq_long_text_multiline(self): a = "1\n" * 100 + "a" + "2\n" * 100 @@ -149,7 +149,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:60: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ - self = + self = def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] @@ -160,7 +160,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:63: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ - self = + self = def test_eq_list_long(self): a = [0] * 100 + [1] + [3] * 100 @@ -173,7 +173,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:68: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ - self = + self = def test_eq_dict(self): > assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0} @@ -190,7 +190,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:71: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ - self = + self = def test_eq_set(self): > assert {0, 10, 11, 12} == {0, 20, 21} @@ -207,7 +207,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:74: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ - self = + self = def test_eq_longer_list(self): > assert [1, 2] == [1, 2, 3] @@ -218,7 +218,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:77: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ - self = + self = def test_in_list(self): > assert 1 in [0, 2, 3, 4, 5] @@ -227,7 +227,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:80: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ - self = + self = def test_not_in_text_multiline(self): text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail" @@ -245,7 +245,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:84: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ - self = + self = def test_not_in_text_single(self): text = "single foo line" @@ -258,7 +258,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:88: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ - self = + self = def test_not_in_text_single_long(self): text = "head " * 50 + "foo " + "tail " * 20 @@ -271,7 +271,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:92: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ - self = + self = def test_not_in_text_single_long_term(self): text = "head " * 50 + "f" * 70 + "tail " * 20 @@ -284,7 +284,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:96: AssertionError ______________ TestSpecialisedExplanations.test_eq_dataclass _______________ - self = + self = def test_eq_dataclass(self): from dataclasses import dataclass @@ -311,7 +311,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:108: AssertionError ________________ TestSpecialisedExplanations.test_eq_attrs _________________ - self = + self = def test_eq_attrs(self): import attr @@ -345,7 +345,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: i = Foo() > assert i.b == 2 E assert 1 == 2 - E + where 1 = .Foo object at 0xdeadbeef0017>.b + E + where 1 = .Foo object at 0xdeadbeef0018>.b failure_demo.py:128: AssertionError _________________________ test_attribute_instance __________________________ @@ -356,8 +356,8 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert Foo().b == 2 E AssertionError: assert 1 == 2 - E + where 1 = .Foo object at 0xdeadbeef0018>.b - E + where .Foo object at 0xdeadbeef0018> = .Foo'>() + E + where 1 = .Foo object at 0xdeadbeef0019>.b + E + where .Foo object at 0xdeadbeef0019> = .Foo'>() failure_demo.py:135: AssertionError __________________________ test_attribute_failure __________________________ @@ -375,7 +375,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:146: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - self = .Foo object at 0xdeadbeef0019> + self = .Foo object at 0xdeadbeef001a> def _get_b(self): > raise Exception("Failed to get attrib") @@ -393,15 +393,15 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert Foo().b == Bar().b E AssertionError: assert 1 == 2 - E + where 1 = .Foo object at 0xdeadbeef001a>.b - E + where .Foo object at 0xdeadbeef001a> = .Foo'>() - E + and 2 = .Bar object at 0xdeadbeef001b>.b - E + where .Bar object at 0xdeadbeef001b> = .Bar'>() + E + where 1 = .Foo object at 0xdeadbeef001b>.b + E + where .Foo object at 0xdeadbeef001b> = .Foo'>() + E + and 2 = .Bar object at 0xdeadbeef001c>.b + E + where .Bar object at 0xdeadbeef001c> = .Bar'>() failure_demo.py:156: AssertionError __________________________ TestRaises.test_raises __________________________ - self = + self = def test_raises(self): s = "qwe" @@ -411,7 +411,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:166: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ - self = + self = def test_raises_doesnt(self): > raises(OSError, int, "3") @@ -420,7 +420,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:169: Failed __________________________ TestRaises.test_raise ___________________________ - self = + self = def test_raise(self): > raise ValueError("demo error") @@ -429,7 +429,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:172: ValueError ________________________ TestRaises.test_tupleerror ________________________ - self = + self = def test_tupleerror(self): > a, b = [1] # NOQA @@ -438,7 +438,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:175: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ - self = + self = def test_reinterpret_fails_with_print_for_the_fun_of_it(self): items = [1, 2, 3] @@ -451,7 +451,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: items is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ - self = + self = def test_some_error(self): > if namenotexi: # NOQA @@ -482,7 +482,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: abc-123:2: AssertionError ____________________ TestMoreErrors.test_complex_error _____________________ - self = + self = def test_complex_error(self): def f(): @@ -508,7 +508,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:6: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ - self = + self = def test_z1_unpack_error(self): items = [] @@ -518,7 +518,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:217: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ - self = + self = def test_z2_type_error(self): items = 3 @@ -528,20 +528,20 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:221: TypeError ______________________ TestMoreErrors.test_startswith ______________________ - self = + self = def test_startswith(self): s = "123" g = "456" > assert s.startswith(g) E AssertionError: assert False - E + where False = ('456') - E + where = '123'.startswith + E + where False = ('456') + E + where = '123'.startswith failure_demo.py:226: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ - self = + self = def test_startswith_nested(self): def f(): @@ -552,15 +552,15 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert f().startswith(g()) E AssertionError: assert False - E + where False = ('456') - E + where = '123'.startswith - E + where '123' = .f at 0xdeadbeef0028>() - E + and '456' = .g at 0xdeadbeef0029>() + E + where False = ('456') + E + where = '123'.startswith + E + where '123' = .f at 0xdeadbeef0029>() + E + and '456' = .g at 0xdeadbeef002a>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:238: 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:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -618,7 +618,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -637,7 +637,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 89bc1aa02ee..8c9c4e75adf 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 7.2.0.dev534+ga2c84caaa.d20230317 + pytest 7.3.0 .. _`simpletest`: From 22951bba6746b1a8a3e783789a18c4518b22ab33 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 9 Apr 2023 00:22:30 +0000 Subject: [PATCH 011/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 70 ++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index d558ccf5707..5887e1192b7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,14 +11,14 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1231 plugins. +This list contains 1233 plugins. .. only:: not latex =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ name summary last release status requires =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ - :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Mar 27, 2023 N/A N/A + :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) @@ -37,7 +37,7 @@ This list contains 1231 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 04, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Feb 03, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 06, 2023 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -251,7 +251,7 @@ This list contains 1231 plugins. :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 25, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Aug 16, 2022 5 - Production/Stable pytest (>=7.1) + :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) :pypi:`pytest-data-extractor` A pytest plugin to extract relevant metadata about tests into an external file (currently only json support) Jul 19, 2022 N/A pytest (>=7.0.1) @@ -459,7 +459,7 @@ This list contains 1231 plugins. :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Feb 10, 2023 4 - Beta pytest (~=7.2) :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) - :pypi:`pytest-flexreport` Apr 01, 2023 4 - Beta pytest + :pypi:`pytest-flexreport` Apr 05, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest @@ -514,14 +514,14 @@ This list contains 1231 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 01, 2023 3 - Alpha pytest (==7.2.2) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 07, 2023 3 - Alpha pytest (==7.2.2) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Mar 05, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Apr 08, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A @@ -556,7 +556,7 @@ This list contains 1231 plugins. :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Feb 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 21, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0) @@ -609,7 +609,7 @@ This list contains 1231 plugins. :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest :pypi:`pytest-lark` A package for enhancing pytest Nov 20, 2022 N/A N/A - :pypi:`pytest-launchable` Launchable Pytest Plugin Jun 14, 2022 N/A pytest (>=4.2.0) + :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Mar 11, 2023 N/A pytest (>=7.2.1,<8.0.0) @@ -672,6 +672,7 @@ This list contains 1231 plugins. :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Apr 06, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) @@ -738,14 +739,14 @@ This list contains 1231 plugins. :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 20, 2022 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-oar` PyTest plugin for the OAR testing framework Mar 31, 2023 N/A pytest>=6.0.1 + :pypi:`pytest-oar` PyTest plugin for the OAR testing framework Apr 04, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odoo` py.test plugin to run Odoo tests Nov 17, 2022 4 - Beta pytest (>=7.2.0) :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 Mar 08, 2023 N/A N/A + :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 Apr 03, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A @@ -825,7 +826,7 @@ This list contains 1231 plugins. :pypi:`pytest-pot` A package for enhancing pytest Nov 20, 2022 N/A N/A :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) - :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Mar 22, 2023 5 - Production/Stable pytest>=7 + :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Dec 28, 2021 5 - Production/Stable pytest (>=6) @@ -862,6 +863,7 @@ This list contains 1231 plugins. :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvista` Pytest-pyvista package Mar 19, 2023 4 - Beta pytest>=3.5.0 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Apr 07, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 26, 2022 5 - Production/Stable pytest (>=6.2.3) @@ -1099,7 +1101,7 @@ This list contains 1231 plugins. :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures Dec 01, 2022 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods Mar 25, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods Apr 06, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5) @@ -1162,7 +1164,7 @@ This list contains 1231 plugins. :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Mar 30, 2023 4 - Beta N/A + :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Apr 06, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) @@ -1255,7 +1257,7 @@ This list contains 1231 plugins. :pypi:`pytest-abq` - *last release*: Mar 27, 2023, + *last release*: Apr 07, 2023, *status*: N/A, *requires*: N/A @@ -1388,7 +1390,7 @@ This list contains 1231 plugins. :pypi:`pytest-alembic` - *last release*: Feb 03, 2023, + *last release*: Apr 06, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -2886,7 +2888,7 @@ This list contains 1231 plugins. pytest plugin for test data directories and files :pypi:`pytest-datadir-mgr` - *last release*: Aug 16, 2022, + *last release*: Apr 06, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=7.1) @@ -4342,7 +4344,7 @@ This list contains 1231 plugins. Run tests in transactions using pytest, Flask, and SQLalchemy. :pypi:`pytest-flexreport` - *last release*: Apr 01, 2023, + *last release*: Apr 05, 2023, *status*: 4 - Beta, *requires*: pytest @@ -4727,7 +4729,7 @@ This list contains 1231 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 01, 2023, + *last release*: Apr 07, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.2.2) @@ -4776,7 +4778,7 @@ This list contains 1231 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Mar 05, 2023, + *last release*: Apr 08, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=6.0.0,>=5.0) @@ -5021,7 +5023,7 @@ This list contains 1231 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Feb 21, 2023, + *last release*: Apr 03, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5392,7 +5394,7 @@ This list contains 1231 plugins. A package for enhancing pytest :pypi:`pytest-launchable` - *last release*: Jun 14, 2022, + *last release*: Apr 05, 2023, *status*: N/A, *requires*: pytest (>=4.2.0) @@ -5832,6 +5834,13 @@ This list contains 1231 plugins. Custom metrics report for pytest + :pypi:`pytest-mh` + *last release*: Apr 06, 2023, + *status*: N/A, + *requires*: pytest + + Pytest multihost plugin + :pypi:`pytest-mimesis` *last release*: Mar 21, 2020, *status*: 5 - Production/Stable, @@ -6295,7 +6304,7 @@ This list contains 1231 plugins. A pytest plugin for generating NUnit3 test result XML output :pypi:`pytest-oar` - *last release*: Mar 31, 2023, + *last release*: Apr 04, 2023, *status*: N/A, *requires*: pytest>=6.0.1 @@ -6344,7 +6353,7 @@ This list contains 1231 plugins. :pypi:`pytest-ogsm-plugin` - *last release*: Mar 08, 2023, + *last release*: Apr 03, 2023, *status*: N/A, *requires*: N/A @@ -6904,7 +6913,7 @@ This list contains 1231 plugins. A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. :pypi:`pytest-pretty` - *last release*: Mar 22, 2023, + *last release*: Apr 05, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7 @@ -7162,6 +7171,13 @@ This list contains 1231 plugins. Pytest-pyvista package + :pypi:`pytest-qaseio` + *last release*: Apr 07, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.2.2,<8.0.0) + + Pytest plugin for Qase.io integration + :pypi:`pytest-qasync` *last release*: Jul 12, 2021, *status*: 4 - Beta, @@ -8822,7 +8838,7 @@ This list contains 1231 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Mar 25, 2023, + *last release*: Apr 06, 2023, *status*: 4 - Beta, *requires*: pytest (<8,>=5) @@ -9263,7 +9279,7 @@ This list contains 1231 plugins. Test Class Base :pypi:`pytest-tui` - *last release*: Mar 30, 2023, + *last release*: Apr 06, 2023, *status*: 4 - Beta, *requires*: N/A From e4e13dd913ebdb333e5dabf7f63c8ffcc4006c4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 08:21:27 -0300 Subject: [PATCH 012/157] build(deps): Bump django in /testing/plugins_integration (#10886) Bumps [django](https://github.com/django/django) from 4.1.7 to 4.2. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/4.1.7...4.2) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 3a6765f65ce..44889c506c2 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.6.2 -django==4.1.7 +django==4.2 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 pytest-cov==4.0.0 From be9faa68d8887a071acb9b6ad3937be444e60008 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 08:25:35 -0300 Subject: [PATCH 013/157] build(deps): Bump peter-evans/create-pull-request from 4.2.4 to 5.0.0 (#10887) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.4 to 5.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/38e0b6e68b4c852a5500a94740f0e535e0d7ba54...5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index d434e6dfc69..ef92fef8836 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -38,7 +38,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@38e0b6e68b4c852a5500a94740f0e535e0d7ba54 + uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 6dcd652d4a55bacda01a15017e155caa816e15a5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 10 Apr 2023 13:04:02 -0300 Subject: [PATCH 014/157] Amend changelog note for removal of attrs (#10888) As discussed in https://github.com/pytest-dev/pytest/pull/10669#issuecomment-1501497729, we should make the reasoning behind this change more clear, as well as thank the attrs maintainers for the many years of cooperation and support. Co-authored-by: Pierre Sassoulas --- doc/en/changelog.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 4fc959c6b19..e57e4fd72a4 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -95,7 +95,12 @@ Improved Documentation Trivial/Internal Changes ------------------------ -- `#10669 `_: pytest no longer depends on the `attrs` package (don't worry, nice diffs for attrs classes are still supported). +- `#10669 `_: pytest no longer directly depends on the `attrs `__ package. While + we at pytest all love the package dearly and would like to thank the ``attrs`` team for many years of cooperation and support, + it makes sense for ``pytest`` to have as little external dependencies as possible, as this helps downstream projects. + With that in mind, we have replaced the pytest's limited internal usage to use the standard library's ``dataclasses`` instead. + + Nice diffs for ``attrs`` classes are still supported though. pytest 7.2.2 (2023-03-03) From 22524046cff84c66f128da9e3cdb993082445c75 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 07:08:45 +0200 Subject: [PATCH 015/157] [pre-commit.ci] pre-commit autoupdate (#10891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.1.1 → v1.2.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.1.1...v1.2.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d672875962f..ca20aec29fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -58,7 +58,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.1.1 + rev: v1.2.0 hooks: - id: mypy files: ^(src/|testing/) From 1b196fbeaf7e9048054cb411d911237eba6a74a9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Apr 2023 12:48:51 +0300 Subject: [PATCH 016/157] pathlib: fix Python 3.12 rmtree(onerror=...) deprecation Fixes #10890 Ref: https://docs.python.org/3.12/library/shutil.html#shutil.rmtree --- changelog/10890.improvement.rst | 1 + src/_pytest/pathlib.py | 32 +++++++++++++++++++++++++------- testing/test_tmpdir.py | 12 ++++++------ 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 changelog/10890.improvement.rst diff --git a/changelog/10890.improvement.rst b/changelog/10890.improvement.rst new file mode 100644 index 00000000000..9c367da31ef --- /dev/null +++ b/changelog/10890.improvement.rst @@ -0,0 +1 @@ +Python 3.12 support: fixed ``shutil.rmtree(onerror=...)`` deprecation warning when using :fixture:`tmp_path`. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 9f9463d8862..30ed76cf89e 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -6,6 +6,7 @@ import os import shutil import sys +import types import uuid import warnings from enum import Enum @@ -28,6 +29,8 @@ from typing import Iterator from typing import Optional from typing import Set +from typing import Tuple +from typing import Type from typing import TypeVar from typing import Union @@ -63,21 +66,33 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath: return path.joinpath(".lock") -def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool: +def on_rm_rf_error( + func, + path: str, + excinfo: Union[ + BaseException, + Tuple[Type[BaseException], BaseException, Optional[types.TracebackType]], + ], + *, + start_path: Path, +) -> bool: """Handle known read-only errors during rmtree. The returned value is used only by our own tests. """ - exctype, excvalue = exc[:2] + if isinstance(excinfo, BaseException): + exc = excinfo + else: + exc = excinfo[1] # Another process removed the file in the middle of the "rm_rf" (xdist for example). # More context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018 - if isinstance(excvalue, FileNotFoundError): + if isinstance(exc, FileNotFoundError): return False - if not isinstance(excvalue, PermissionError): + if not isinstance(exc, PermissionError): warnings.warn( - PytestWarning(f"(rm_rf) error removing {path}\n{exctype}: {excvalue}") + PytestWarning(f"(rm_rf) error removing {path}\n{type(exc)}: {exc}") ) return False @@ -86,7 +101,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool: warnings.warn( PytestWarning( "(rm_rf) unknown function {} when removing {}:\n{}: {}".format( - func, path, exctype, excvalue + func, path, type(exc), exc ) ) ) @@ -149,7 +164,10 @@ def rm_rf(path: Path) -> None: are read-only.""" path = ensure_extended_length_path(path) onerror = partial(on_rm_rf_error, start_path=path) - shutil.rmtree(str(path), onerror=onerror) + if sys.version_info >= (3, 12): + shutil.rmtree(str(path), onexc=onerror) + else: + shutil.rmtree(str(path), onerror=onerror) def find_prefixed(root: Path, prefix: str) -> Iterator[Path]: diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index fcb0775dd5f..110a68b278d 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -512,20 +512,20 @@ def test_on_rm_rf_error(self, tmp_path: Path) -> None: # unknown exception with pytest.warns(pytest.PytestWarning): - exc_info1 = (None, RuntimeError(), None) + exc_info1 = (RuntimeError, RuntimeError(), None) on_rm_rf_error(os.unlink, str(fn), exc_info1, start_path=tmp_path) assert fn.is_file() # we ignore FileNotFoundError - exc_info2 = (None, FileNotFoundError(), None) + exc_info2 = (FileNotFoundError, FileNotFoundError(), None) assert not on_rm_rf_error(None, str(fn), exc_info2, start_path=tmp_path) # unknown function with pytest.warns( pytest.PytestWarning, - match=r"^\(rm_rf\) unknown function None when removing .*foo.txt:\nNone: ", + match=r"^\(rm_rf\) unknown function None when removing .*foo.txt:\n: ", ): - exc_info3 = (None, PermissionError(), None) + exc_info3 = (PermissionError, PermissionError(), None) on_rm_rf_error(None, str(fn), exc_info3, start_path=tmp_path) assert fn.is_file() @@ -533,12 +533,12 @@ def test_on_rm_rf_error(self, tmp_path: Path) -> None: with warnings.catch_warnings(): warnings.simplefilter("ignore") with pytest.warns(None) as warninfo: # type: ignore[call-overload] - exc_info4 = (None, PermissionError(), None) + exc_info4 = PermissionError() on_rm_rf_error(os.open, str(fn), exc_info4, start_path=tmp_path) assert fn.is_file() assert not [x.message for x in warninfo] - exc_info5 = (None, PermissionError(), None) + exc_info5 = PermissionError() on_rm_rf_error(os.unlink, str(fn), exc_info5, start_path=tmp_path) assert not fn.is_file() From 1b81d636e2a086403031909cfb71a397d1ce26de Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Apr 2023 12:53:13 +0300 Subject: [PATCH 017/157] unittest: add addDuration function for Python 3.12 support Fix #10875 Without this, fails with ``` ... E AttributeError: 'TestCaseFunction' object has no attribute 'addDuration' ... E RuntimeWarning: TestResult has no addDuration method ``` --- changelog/10875.improvement.rst | 1 + src/_pytest/unittest.py | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 changelog/10875.improvement.rst diff --git a/changelog/10875.improvement.rst b/changelog/10875.improvement.rst new file mode 100644 index 00000000000..eeaf046350b --- /dev/null +++ b/changelog/10875.improvement.rst @@ -0,0 +1 @@ +Python 3.12 support: fixed ``RuntimeError: TestResult has no addDuration method`` when running ``unittest`` tests. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index c2df986530c..c660aa75db2 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -298,6 +298,9 @@ def addSuccess(self, testcase: "unittest.TestCase") -> None: def stopTest(self, testcase: "unittest.TestCase") -> None: pass + def addDuration(self, testcase: "unittest.TestCase", elapsed: float) -> None: + pass + def runtest(self) -> None: from _pytest.debugging import maybe_wrap_pytest_function_for_tracing From 9c2247ec1b9566266478e6f561cad30079533ed5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 12:09:35 +0300 Subject: [PATCH 018/157] code: drop Experimental API label from ExceptionInfo.from_exc_info This API is OK, I don't think we're going to change something about it at this point. --- src/_pytest/_code/code.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 032b83beb02..6fd1100dfc4 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -476,10 +476,6 @@ def from_exc_info( ) -> "ExceptionInfo[E]": """Return an ExceptionInfo for an existing exc_info tuple. - .. warning:: - - Experimental API - :param exprinfo: A text string helping to determine if we should strip ``AssertionError`` from the output. Defaults to the exception From 424c3eebde1192b671767359c23b6344c795dc70 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 12:24:59 +0300 Subject: [PATCH 019/157] code: add ExceptionInfo.from_exception The old-style `sys.exc_info()` triplet is redundant nowadays with `(type(exc), exc, exc.__traceback__)`, and is beginning to get soft-deprecated in Python 3.12. Add a nicer API to ExceptionInfo which takes just the exc instead of the triplet. There are already a few internal uses which benefit. --- changelog/10901.feature.rst | 2 ++ src/_pytest/_code/code.py | 43 ++++++++++++++++++++++-------------- src/_pytest/python_api.py | 6 +---- testing/code/test_excinfo.py | 14 ++++++++++++ 4 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 changelog/10901.feature.rst diff --git a/changelog/10901.feature.rst b/changelog/10901.feature.rst new file mode 100644 index 00000000000..0d99d66f67f --- /dev/null +++ b/changelog/10901.feature.rst @@ -0,0 +1,2 @@ +Added :func:`ExceptionInfo.from_exception() `, a simpler way to create an :class:`~pytest.ExceptionInfo` from an exception. +This can replace :func:`ExceptionInfo.from_exc_info() ` for most uses. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 032b83beb02..e2451bcdf7d 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -469,22 +469,41 @@ def __init__( self._traceback = traceback @classmethod - def from_exc_info( + def from_exception( cls, - exc_info: Tuple[Type[E], E, TracebackType], + # Ignoring error: "Cannot use a covariant type variable as a parameter". + # This is OK to ignore because this class is (conceptually) readonly. + # See https://github.com/python/mypy/issues/7049. + exception: E, # type: ignore[misc] exprinfo: Optional[str] = None, ) -> "ExceptionInfo[E]": - """Return an ExceptionInfo for an existing exc_info tuple. - - .. warning:: + """Return an ExceptionInfo for an existing exception. - Experimental API + The exception must have a non-``None`` ``__traceback__`` attribute, + otherwise this function fails with an assertion error. This means that + the exception must have been raised, or added a traceback with the + :py:meth:`~BaseException.with_traceback()` method. :param exprinfo: A text string helping to determine if we should strip ``AssertionError`` from the output. Defaults to the exception message/``__str__()``. + + .. versionadded:: 7.4 """ + assert ( + exception.__traceback__ + ), "Exceptions passed to ExcInfo.from_exception(...) must have a non-None __traceback__." + exc_info = (type(exception), exception, exception.__traceback__) + return cls.from_exc_info(exc_info, exprinfo) + + @classmethod + def from_exc_info( + cls, + exc_info: Tuple[Type[E], E, TracebackType], + exprinfo: Optional[str] = None, + ) -> "ExceptionInfo[E]": + """Like :func:`from_exception`, but using old-style exc_info tuple.""" _striptext = "" if exprinfo is None and isinstance(exc_info[1], AssertionError): exprinfo = getattr(exc_info[1], "msg", None) @@ -965,21 +984,13 @@ def repr_excinfo( if e.__cause__ is not None and self.chain: e = e.__cause__ - excinfo_ = ( - ExceptionInfo.from_exc_info((type(e), e, e.__traceback__)) - if e.__traceback__ - else None - ) + excinfo_ = ExceptionInfo.from_exception(e) if e.__traceback__ else None descr = "The above exception was the direct cause of the following exception:" elif ( e.__context__ is not None and not e.__suppress_context__ and self.chain ): e = e.__context__ - excinfo_ = ( - ExceptionInfo.from_exc_info((type(e), e, e.__traceback__)) - if e.__traceback__ - else None - ) + excinfo_ = ExceptionInfo.from_exception(e) if e.__traceback__ else None descr = "During handling of the above exception, another exception occurred:" else: e = None diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index b03a251abaf..4213bd098c2 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -950,11 +950,7 @@ def raises( # noqa: F811 try: func(*args[1:], **kwargs) except expected_exception as e: - # We just caught the exception - there is a traceback. - assert e.__traceback__ is not None - return _pytest._code.ExceptionInfo.from_exc_info( - (type(e), e, e.__traceback__) - ) + return _pytest._code.ExceptionInfo.from_exception(e) fail(message) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 918c972762b..8ac8a42ab73 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -53,6 +53,20 @@ def test_excinfo_from_exc_info_simple() -> None: assert info.type == ValueError +def test_excinfo_from_exception_simple() -> None: + try: + raise ValueError + except ValueError as e: + assert e.__traceback__ is not None + info = _pytest._code.ExceptionInfo.from_exception(e) + assert info.type == ValueError + + +def test_excinfo_from_exception_missing_traceback_assertion() -> None: + with pytest.raises(AssertionError, match=r"must have.*__traceback__"): + _pytest._code.ExceptionInfo.from_exception(ValueError()) + + def test_excinfo_getstatement(): def g(): raise ValueError From 90412827c3c87ceb1a903743110f0b892f13feec Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 18:35:59 +0300 Subject: [PATCH 020/157] Revert "Correctly handle tracebackhide for chained exceptions (#10772)" This reverts commit 431ec6d34ef99d80f90b330876ed6231144a3ce7. Fix #10903. Reopen #1904. --- AUTHORS | 1 - changelog/10903.bugfix.rst | 2 ++ doc/en/changelog.rst | 1 + src/_pytest/_code/code.py | 27 ++++++++++----------------- src/_pytest/reports.py | 4 ---- testing/code/test_excinfo.py | 23 +++++++++++++++++++++-- testing/test_tracebackhide.py | 25 ------------------------- 7 files changed, 34 insertions(+), 49 deletions(-) create mode 100644 changelog/10903.bugfix.rst delete mode 100644 testing/test_tracebackhide.py diff --git a/AUTHORS b/AUTHORS index 1aa5265e62e..a4c7f856884 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,7 +128,6 @@ Erik M. Bray Evan Kepner Fabien Zarifian Fabio Zadrozny -Felix Hofstätter Felix Nieuwenhuizen Feng Ma Florian Bruhin diff --git a/changelog/10903.bugfix.rst b/changelog/10903.bugfix.rst new file mode 100644 index 00000000000..34fbcd00221 --- /dev/null +++ b/changelog/10903.bugfix.rst @@ -0,0 +1,2 @@ +Fix crash ``INTERNALERROR IndexError: list index out of range`` which happens when displaying an exception where all entries are hidden. +This reverts the change "Correctly handle ``__tracebackhide__`` for chained exceptions." introduced in version 7.3.0. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index e57e4fd72a4..5a2a26b87f4 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -82,6 +82,7 @@ Bug Fixes - `#1904 `_: Correctly handle ``__tracebackhide__`` for chained exceptions. + NOTE: This change was reverted in version 7.3.1. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 032b83beb02..9024cc0133f 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -411,13 +411,13 @@ def filter( """ return Traceback(filter(fn, self), self._excinfo) - def getcrashentry(self) -> Optional[TracebackEntry]: + def getcrashentry(self) -> TracebackEntry: """Return last non-hidden traceback entry that lead to the exception of a traceback.""" for i in range(-1, -len(self) - 1, -1): entry = self[i] if not entry.ishidden(): return entry - return None + return self[-1] def recursionindex(self) -> Optional[int]: """Return the index of the frame/TracebackEntry where recursion originates if @@ -602,13 +602,11 @@ def errisinstance( """ return isinstance(self.value, exc) - def _getreprcrash(self) -> Optional["ReprFileLocation"]: + def _getreprcrash(self) -> "ReprFileLocation": exconly = self.exconly(tryshort=True) entry = self.traceback.getcrashentry() - if entry: - path, lineno = entry.frame.code.raw.co_filename, entry.lineno - return ReprFileLocation(path, lineno + 1, exconly) - return None + path, lineno = entry.frame.code.raw.co_filename, entry.lineno + return ReprFileLocation(path, lineno + 1, exconly) def getrepr( self, @@ -946,14 +944,9 @@ def repr_excinfo( ) else: reprtraceback = self.repr_traceback(excinfo_) - - # will be None if all traceback entries are hidden - reprcrash: Optional[ReprFileLocation] = excinfo_._getreprcrash() - if reprcrash: - if self.style == "value": - repr_chain += [(reprtraceback, None, descr)] - else: - repr_chain += [(reprtraceback, reprcrash, descr)] + reprcrash: Optional[ReprFileLocation] = ( + excinfo_._getreprcrash() if self.style != "value" else None + ) else: # Fallback to native repr if the exception doesn't have a traceback: # ExceptionInfo objects require a full traceback to work. @@ -961,8 +954,8 @@ def repr_excinfo( traceback.format_exception(type(e), e, None) ) reprcrash = None - repr_chain += [(reprtraceback, reprcrash, descr)] + repr_chain += [(reprtraceback, reprcrash, descr)] if e.__cause__ is not None and self.chain: e = e.__cause__ excinfo_ = ( @@ -1053,7 +1046,7 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ReprExceptionInfo(ExceptionRepr): reprtraceback: "ReprTraceback" - reprcrash: Optional["ReprFileLocation"] + reprcrash: "ReprFileLocation" def toterminal(self, tw: TerminalWriter) -> None: self.reprtraceback.toterminal(tw) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index c0a76f92b59..2e36514eae5 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -347,10 +347,6 @@ def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": elif isinstance(excinfo.value, skip.Exception): outcome = "skipped" r = excinfo._getreprcrash() - if r is None: - raise ValueError( - "There should always be a traceback entry for skipping a test." - ) if excinfo.value._use_item_location: path, line = item.reportinfo()[:2] assert line is not None diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 918c972762b..957ac6fc5ae 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -294,7 +294,6 @@ def f(): excinfo = pytest.raises(ValueError, f) tb = excinfo.traceback entry = tb.getcrashentry() - assert entry is not None co = _pytest._code.Code.from_function(h) assert entry.frame.code.path == co.path assert entry.lineno == co.firstlineno + 1 @@ -312,7 +311,10 @@ def f(): excinfo = pytest.raises(ValueError, f) tb = excinfo.traceback entry = tb.getcrashentry() - assert entry is None + co = _pytest._code.Code.from_function(g) + assert entry.frame.code.path == co.path + assert entry.lineno == co.firstlineno + 2 + assert entry.frame.code.name == "g" def test_excinfo_exconly(): @@ -1573,3 +1575,20 @@ def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None: # with py>=3.11 does not depend on exceptiongroup, though there is a toxenv for it pytest.importorskip("exceptiongroup") _exceptiongroup_common(pytester, outer_chain, inner_chain, native=False) + + +def test_all_entries_hidden_doesnt_crash(pytester: Pytester) -> None: + """Regression test for #10903. + + We're not really sure what should be *displayed* here, so this test + just verified that at least it doesn't crash. + """ + pytester.makepyfile( + """ + def test(): + __tracebackhide__ = True + 1 / 0 + """ + ) + result = pytester.runpytest() + assert result.ret == 1 diff --git a/testing/test_tracebackhide.py b/testing/test_tracebackhide.py deleted file mode 100644 index 88f9c4fc00e..00000000000 --- a/testing/test_tracebackhide.py +++ /dev/null @@ -1,25 +0,0 @@ -def test_tbh_chained(testdir): - """Ensure chained exceptions whose frames contain "__tracebackhide__" are not shown (#1904).""" - p = testdir.makepyfile( - """ - import pytest - - def f1(): - __tracebackhide__ = True - try: - return f1.meh - except AttributeError: - pytest.fail("fail") - - @pytest.fixture - def fix(): - f1() - - - def test(fix): - pass - """ - ) - result = testdir.runpytest(str(p)) - assert "'function' object has no attribute 'meh'" not in result.stdout.str() - assert result.ret == 1 From e3b179976666b53f170b95c586322e1feb483a3c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 22:03:31 +0300 Subject: [PATCH 021/157] code: handle repr'ing empty tracebacks gracefully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By "empty traceback" I mean a traceback all of whose entries have been filtered/cut/pruned out. Currently, if an empty traceback needs to be repr'ed, the last entry before the filtering is used instead (added in accd962c9f88dbd5b2b0eef6efe7bf6fe5444b29). Showing a hidden frame is not so good IMO. This commit does the following instead: 1. Shows details of the exception. 2. Shows a message about how the full trace can be seen. Example: ``` _____________ test _____________ E ZeroDivisionError: division by zero All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames. ``` Also handles `--tb=native`, though there the `--full-trace` bit is not shown. This commit contains some pieces from 431ec6d34ef99d80f90b330876ed6231144a3ce7 (which has been reverted). Helps towards fixing issue # 1904. Co-authored-by: Felix Hofstätter --- AUTHORS | 1 + src/_pytest/_code/code.py | 52 +++++++++++++++++++++++------------- src/_pytest/nodes.py | 3 --- src/_pytest/reports.py | 3 +++ testing/code/test_excinfo.py | 23 +++++++--------- 5 files changed, 47 insertions(+), 35 deletions(-) diff --git a/AUTHORS b/AUTHORS index a4c7f856884..1aa5265e62e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,6 +128,7 @@ Erik M. Bray Evan Kepner Fabien Zarifian Fabio Zadrozny +Felix Hofstätter Felix Nieuwenhuizen Feng Ma Florian Bruhin diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 872bea38bd1..2eabe583195 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -411,13 +411,14 @@ def filter( """ return Traceback(filter(fn, self), self._excinfo) - def getcrashentry(self) -> TracebackEntry: - """Return last non-hidden traceback entry that lead to the exception of a traceback.""" + def getcrashentry(self) -> Optional[TracebackEntry]: + """Return last non-hidden traceback entry that lead to the exception of + a traceback, or None if all hidden.""" for i in range(-1, -len(self) - 1, -1): entry = self[i] if not entry.ishidden(): return entry - return self[-1] + return None def recursionindex(self) -> Optional[int]: """Return the index of the frame/TracebackEntry where recursion originates if @@ -598,9 +599,11 @@ def errisinstance( """ return isinstance(self.value, exc) - def _getreprcrash(self) -> "ReprFileLocation": + def _getreprcrash(self) -> Optional["ReprFileLocation"]: exconly = self.exconly(tryshort=True) entry = self.traceback.getcrashentry() + if entry is None: + return None path, lineno = entry.frame.code.raw.co_filename, entry.lineno return ReprFileLocation(path, lineno + 1, exconly) @@ -647,7 +650,9 @@ def getrepr( return ReprExceptionInfo( reprtraceback=ReprTracebackNative( traceback.format_exception( - self.type, self.value, self.traceback[0]._rawentry + self.type, + self.value, + self.traceback[0]._rawentry if self.traceback else None, ) ), reprcrash=self._getreprcrash(), @@ -803,12 +808,16 @@ def repr_locals(self, locals: Mapping[str, object]) -> Optional["ReprLocals"]: def repr_traceback_entry( self, - entry: TracebackEntry, + entry: Optional[TracebackEntry], excinfo: Optional[ExceptionInfo[BaseException]] = None, ) -> "ReprEntry": lines: List[str] = [] - style = entry._repr_style if entry._repr_style is not None else self.style - if style in ("short", "long"): + style = ( + entry._repr_style + if entry is not None and entry._repr_style is not None + else self.style + ) + if style in ("short", "long") and entry is not None: source = self._getentrysource(entry) if source is None: source = Source("???") @@ -857,17 +866,21 @@ def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTracebac else: extraline = None + if not traceback: + if extraline is None: + extraline = "All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames." + entries = [self.repr_traceback_entry(None, excinfo)] + return ReprTraceback(entries, extraline, style=self.style) + last = traceback[-1] - entries = [] if self.style == "value": - reprentry = self.repr_traceback_entry(last, excinfo) - entries.append(reprentry) + entries = [self.repr_traceback_entry(last, excinfo)] return ReprTraceback(entries, None, style=self.style) - for index, entry in enumerate(traceback): - einfo = (last == entry) and excinfo or None - reprentry = self.repr_traceback_entry(entry, einfo) - entries.append(reprentry) + entries = [ + self.repr_traceback_entry(entry, excinfo if last == entry else None) + for entry in traceback + ] return ReprTraceback(entries, extraline, style=self.style) def _truncate_recursive_traceback( @@ -924,6 +937,7 @@ def repr_excinfo( seen: Set[int] = set() while e is not None and id(e) not in seen: seen.add(id(e)) + if excinfo_: # Fall back to native traceback as a temporary workaround until # full support for exception groups added to ExceptionInfo. @@ -950,8 +964,8 @@ def repr_excinfo( traceback.format_exception(type(e), e, None) ) reprcrash = None - repr_chain += [(reprtraceback, reprcrash, descr)] + if e.__cause__ is not None and self.chain: e = e.__cause__ excinfo_ = ( @@ -1042,7 +1056,7 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ReprExceptionInfo(ExceptionRepr): reprtraceback: "ReprTraceback" - reprcrash: "ReprFileLocation" + reprcrash: Optional["ReprFileLocation"] def toterminal(self, tw: TerminalWriter) -> None: self.reprtraceback.toterminal(tw) @@ -1147,8 +1161,8 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: def toterminal(self, tw: TerminalWriter) -> None: if self.style == "short": - assert self.reprfileloc is not None - self.reprfileloc.toterminal(tw) + if self.reprfileloc: + self.reprfileloc.toterminal(tw) self._write_entry_lines(tw) if self.reprlocals: self.reprlocals.toterminal(tw, indent=" " * 8) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index c74740dbc8a..ea016786e2b 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -452,10 +452,7 @@ def _repr_failure_py( if self.config.getoption("fulltrace", False): style = "long" else: - tb = _pytest._code.Traceback([excinfo.traceback[-1]]) self._prunetraceback(excinfo) - if len(excinfo.traceback) == 0: - excinfo.traceback = tb if style == "auto": style = "long" # XXX should excinfo.getrepr record all data and toterminal() process it? diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 2e36514eae5..74e8794b232 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -347,6 +347,9 @@ def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": elif isinstance(excinfo.value, skip.Exception): outcome = "skipped" r = excinfo._getreprcrash() + assert ( + r is not None + ), "There should always be a traceback entry for skipping a test." if excinfo.value._use_item_location: path, line = item.reportinfo()[:2] assert line is not None diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 957ac6fc5ae..b6793fd724a 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -294,6 +294,7 @@ def f(): excinfo = pytest.raises(ValueError, f) tb = excinfo.traceback entry = tb.getcrashentry() + assert entry is not None co = _pytest._code.Code.from_function(h) assert entry.frame.code.path == co.path assert entry.lineno == co.firstlineno + 1 @@ -309,12 +310,7 @@ def f(): g() excinfo = pytest.raises(ValueError, f) - tb = excinfo.traceback - entry = tb.getcrashentry() - co = _pytest._code.Code.from_function(g) - assert entry.frame.code.path == co.path - assert entry.lineno == co.firstlineno + 2 - assert entry.frame.code.name == "g" + assert excinfo.traceback.getcrashentry() is None def test_excinfo_exconly(): @@ -1577,12 +1573,9 @@ def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None: _exceptiongroup_common(pytester, outer_chain, inner_chain, native=False) -def test_all_entries_hidden_doesnt_crash(pytester: Pytester) -> None: - """Regression test for #10903. - - We're not really sure what should be *displayed* here, so this test - just verified that at least it doesn't crash. - """ +@pytest.mark.parametrize("tbstyle", ("long", "short", "auto", "line", "native")) +def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None: + """Regression test for #10903.""" pytester.makepyfile( """ def test(): @@ -1590,5 +1583,9 @@ def test(): 1 / 0 """ ) - result = pytester.runpytest() + result = pytester.runpytest("--tb", tbstyle) assert result.ret == 1 + if tbstyle != "line": + result.stdout.fnmatch_lines(["*ZeroDivisionError: division by zero"]) + if tbstyle not in ("line", "native"): + result.stdout.fnmatch_lines(["All traceback entries are hidden.*"]) From d38077106556184026137fe83d8351970f08ac89 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 14 Apr 2023 13:24:12 -0300 Subject: [PATCH 022/157] Fix tmp_path regression introduced in 7.3.0 (#10911) The problem is that we would loop over all directories of the basetemp directory searching for dead symlinks, for each test, which would compound over the test session run. Doing the cleanup just once, at the end of the session, fixes the problem. Fix #10896 --- changelog/10896.bugfix.rst | 1 + src/_pytest/pathlib.py | 4 ++-- src/_pytest/tmpdir.py | 21 ++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) create mode 100644 changelog/10896.bugfix.rst diff --git a/changelog/10896.bugfix.rst b/changelog/10896.bugfix.rst new file mode 100644 index 00000000000..87af0e301e5 --- /dev/null +++ b/changelog/10896.bugfix.rst @@ -0,0 +1 @@ +Fixed performance regression related to :fixture:`tmp_path` and the new :confval:`tmp_path_retention_policy` option. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 30ed76cf89e..2c9d5870b50 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -353,7 +353,7 @@ def cleanup_candidates(root: Path, prefix: str, keep: int) -> Iterator[Path]: yield path -def cleanup_dead_symlink(root: Path): +def cleanup_dead_symlinks(root: Path): for left_dir in root.iterdir(): if left_dir.is_symlink(): if not left_dir.resolve().exists(): @@ -371,7 +371,7 @@ def cleanup_numbered_dir( for path in root.glob("garbage-*"): try_cleanup(path, consider_lock_dead_if_created_before) - cleanup_dead_symlink(root) + cleanup_dead_symlinks(root) def make_numbered_dir_with_cleanup( diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 5f347665f9a..d7f5ab9b459 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -28,7 +28,7 @@ from .pathlib import make_numbered_dir from .pathlib import make_numbered_dir_with_cleanup from .pathlib import rm_rf -from .pathlib import cleanup_dead_symlink +from .pathlib import cleanup_dead_symlinks from _pytest.compat import final, get_user_id from _pytest.config import Config from _pytest.config import ExitCode @@ -289,31 +289,30 @@ def tmp_path( del request.node.stash[tmppath_result_key] - # remove dead symlink - basetemp = tmp_path_factory._basetemp - if basetemp is None: - return - cleanup_dead_symlink(basetemp) - def pytest_sessionfinish(session, exitstatus: Union[int, ExitCode]): """After each session, remove base directory if all the tests passed, the policy is "failed", and the basetemp is not specified by a user. """ tmp_path_factory: TempPathFactory = session.config._tmp_path_factory - if tmp_path_factory._basetemp is None: + basetemp = tmp_path_factory._basetemp + if basetemp is None: return + policy = tmp_path_factory._retention_policy if ( exitstatus == 0 and policy == "failed" and tmp_path_factory._given_basetemp is None ): - passed_dir = tmp_path_factory._basetemp - if passed_dir.exists(): + if basetemp.is_dir(): # We do a "best effort" to remove files, but it might not be possible due to some leaked resource, # permissions, etc, in which case we ignore it. - rmtree(passed_dir, ignore_errors=True) + rmtree(basetemp, ignore_errors=True) + + # Remove dead symlinks. + if basetemp.is_dir(): + cleanup_dead_symlinks(basetemp) @hookimpl(tryfirst=True, hookwrapper=True) From ece756fcb4c3ca2bf6368f3abf52db9530930212 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 14 Apr 2023 15:12:22 -0300 Subject: [PATCH 023/157] Merge pull request #10913 from pytest-dev/release-7.3.1 Prepare release 7.3.1 (cherry picked from commit a1f7a204df45a4fd07d5d62128f61198e5dd7f23) --- changelog/10875.improvement.rst | 1 - changelog/10890.improvement.rst | 1 - changelog/10896.bugfix.rst | 1 - changelog/10903.bugfix.rst | 2 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-7.3.1.rst | 18 ++++++++++++++++++ doc/en/changelog.rst | 23 +++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- 8 files changed, 43 insertions(+), 6 deletions(-) delete mode 100644 changelog/10875.improvement.rst delete mode 100644 changelog/10890.improvement.rst delete mode 100644 changelog/10896.bugfix.rst delete mode 100644 changelog/10903.bugfix.rst create mode 100644 doc/en/announce/release-7.3.1.rst diff --git a/changelog/10875.improvement.rst b/changelog/10875.improvement.rst deleted file mode 100644 index eeaf046350b..00000000000 --- a/changelog/10875.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Python 3.12 support: fixed ``RuntimeError: TestResult has no addDuration method`` when running ``unittest`` tests. diff --git a/changelog/10890.improvement.rst b/changelog/10890.improvement.rst deleted file mode 100644 index 9c367da31ef..00000000000 --- a/changelog/10890.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Python 3.12 support: fixed ``shutil.rmtree(onerror=...)`` deprecation warning when using :fixture:`tmp_path`. diff --git a/changelog/10896.bugfix.rst b/changelog/10896.bugfix.rst deleted file mode 100644 index 87af0e301e5..00000000000 --- a/changelog/10896.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed performance regression related to :fixture:`tmp_path` and the new :confval:`tmp_path_retention_policy` option. diff --git a/changelog/10903.bugfix.rst b/changelog/10903.bugfix.rst deleted file mode 100644 index 34fbcd00221..00000000000 --- a/changelog/10903.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash ``INTERNALERROR IndexError: list index out of range`` which happens when displaying an exception where all entries are hidden. -This reverts the change "Correctly handle ``__tracebackhide__`` for chained exceptions." introduced in version 7.3.0. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 96db2e248a7..e3919f88ea6 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.3.1 release-7.3.0 release-7.2.2 release-7.2.1 diff --git a/doc/en/announce/release-7.3.1.rst b/doc/en/announce/release-7.3.1.rst new file mode 100644 index 00000000000..e920fa8af53 --- /dev/null +++ b/doc/en/announce/release-7.3.1.rst @@ -0,0 +1,18 @@ +pytest-7.3.1 +======================================= + +pytest 7.3.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 5a2a26b87f4..c13c05936d5 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,29 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.3.1 (2023-04-14) +========================= + +Improvements +------------ + +- `#10875 `_: Python 3.12 support: fixed ``RuntimeError: TestResult has no addDuration method`` when running ``unittest`` tests. + + +- `#10890 `_: Python 3.12 support: fixed ``shutil.rmtree(onerror=...)`` deprecation warning when using :fixture:`tmp_path`. + + + +Bug Fixes +--------- + +- `#10896 `_: Fixed performance regression related to :fixture:`tmp_path` and the new :confval:`tmp_path_retention_policy` option. + + +- `#10903 `_: Fix crash ``INTERNALERROR IndexError: list index out of range`` which happens when displaying an exception where all entries are hidden. + This reverts the change "Correctly handle ``__tracebackhide__`` for chained exceptions." introduced in version 7.3.0. + + pytest 7.3.0 (2023-04-08) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 8c9c4e75adf..f4157114153 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 7.3.0 + pytest 7.3.1 .. _`simpletest`: From 28783e5d23beb23de8f2abff04c7cfada00c9f8b Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 16 Apr 2023 00:21:39 +0000 Subject: [PATCH 024/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 148 ++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 50 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 5887e1192b7..a6fa69d54f5 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1233 plugins. +This list contains 1239 plugins. .. only:: not latex @@ -41,7 +41,7 @@ This list contains 1233 plugins. :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) - :pypi:`pytest-allure-collection` pytest plugin to collect allure markers without running any tests Oct 21, 2022 N/A pytest + :pypi:`pytest-allure-collection` pytest plugin to collect allure markers without running any tests Apr 13, 2023 N/A pytest :pypi:`pytest-allure-dsl` pytest plugin to test case doc string dls instructions Oct 25, 2020 4 - Beta pytest :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest @@ -49,7 +49,7 @@ This list contains 1233 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for py.test to simplify calling ansible modules from tests or fixtures May 25, 2021 5 - Production/Stable N/A + :pypi:`pytest-ansible` Plugin for py.test to simplify calling ansible modules from tests or fixtures Apr 14, 2023 5 - Production/Stable pytest (<8.0.0,>=6) :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -279,7 +279,7 @@ This list contains 1233 plugins. :pypi:`pytest-dependency` Manage dependencies of tests Feb 14, 2020 4 - Beta N/A :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A - :pypi:`pytest-describe` Describe-style plugin for pytest Nov 13, 2021 4 - Beta pytest (>=4.0.0) + :pypi:`pytest-describe` Describe-style plugin for pytest Apr 09, 2023 5 - Production/Stable pytest (<8,>=4.6) :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A @@ -365,16 +365,16 @@ This list contains 1233 plugins. :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` pytest embedded plugin Mar 10, 2023 N/A pytest (>=7.0) - :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects Mar 10, 2023 N/A N/A - :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project Mar 10, 2023 N/A N/A - :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag Mar 10, 2023 N/A N/A - :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip Mar 10, 2023 N/A N/A - :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports Mar 10, 2023 N/A N/A - :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports Mar 10, 2023 N/A N/A + :pypi:`pytest-embedded` pytest embedded plugin Apr 11, 2023 N/A pytest (>=7.0) + :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports Apr 11, 2023 N/A N/A :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) - :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 12, 2022 4 - Beta pytest (==7.0.1) + :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) :pypi:`pytest-enabler` Enable installed pytest plugins Jan 27, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest @@ -402,6 +402,7 @@ This list contains 1233 plugins. :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A :pypi:`pytest-expectr` This plugin is used to expect multiple assert using pytest framework. Oct 05, 2018 N/A pytest (>=2.4.2) + :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest :pypi:`pytest-exploratory` Interactive console for pytest. Feb 21, 2022 N/A pytest (>=6.2) @@ -459,7 +460,7 @@ This list contains 1233 plugins. :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Feb 10, 2023 4 - Beta pytest (~=7.2) :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) - :pypi:`pytest-flexreport` Apr 05, 2023 4 - Beta pytest + :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest @@ -467,6 +468,7 @@ This list contains 1233 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Apr 14, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Oct 20, 2022 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -496,6 +498,7 @@ This list contains 1233 plugins. :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) + :pypi:`pytest-goldie` A plugin to support golden tests with pytest. Apr 12, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A @@ -514,7 +517,7 @@ This list contains 1233 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 07, 2023 3 - Alpha pytest (==7.2.2) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 14, 2023 3 - Alpha pytest (==7.2.2) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) @@ -535,7 +538,7 @@ This list contains 1233 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest Sep 12, 2022 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Mar 15, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Jan 20, 2023 5 - Production/Stable pytest (<8.0,>=6.0) + :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest @@ -555,7 +558,7 @@ This list contains 1233 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-inmanta-extensions` Inmanta tests package Feb 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 12, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -566,7 +569,7 @@ This list contains 1233 plugins. :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0) :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Mar 24, 2023 5 - Production/Stable pytest (<7.2.0,>=6) + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 13, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -592,6 +595,7 @@ This list contains 1233 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 30, 2023 4 - Beta pytest + :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 13, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Oct 01, 2022 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) @@ -702,6 +706,7 @@ This list contains 1233 plugins. :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest + :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Mar 15, 2023 4 - Beta pytest (<8) ; extra == 'test' @@ -718,7 +723,7 @@ This list contains 1233 plugins. :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jan 11, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Apr 11, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -972,21 +977,21 @@ This list contains 1233 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 28, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 15, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 28, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 15, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Feb 24, 2023 3 - Alpha pytest (>=6.2) + :pypi:`pytest-servers` pytest servers Apr 15, 2023 3 - Alpha pytest (>=6.2) :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1040,7 +1045,7 @@ This list contains 1233 plugins. :pypi:`pytest-spiratest` Exports unit tests as test runs in SpiraTest/Team/Plan Feb 08, 2022 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) - :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 22, 2022 4 - Beta pytest (>=5,<8) + :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A @@ -1073,7 +1078,7 @@ This list contains 1233 plugins. :pypi:`pytest-subtesthack` A hack to explicitly set up and tear down fixtures. Jul 16, 2022 N/A N/A :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Feb 16, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Aug 29, 2017 N/A N/A - :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Nov 05, 2022 3 - Alpha pytest (>=2.9) + :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) @@ -1081,6 +1086,7 @@ This list contains 1233 plugins. :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A + :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. Apr 13, 2023 3 - Alpha pytest (>=6.2.5) :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -1418,7 +1424,7 @@ This list contains 1233 plugins. Plugin for py.test to generate allure xml reports :pypi:`pytest-allure-collection` - *last release*: Oct 21, 2022, + *last release*: Apr 13, 2023, *status*: N/A, *requires*: pytest @@ -1474,9 +1480,9 @@ This list contains 1233 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: May 25, 2021, + *last release*: Apr 14, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest (<8.0.0,>=6) Plugin for py.test to simplify calling ansible modules from tests or fixtures @@ -3084,9 +3090,9 @@ This list contains 1233 plugins. Mark tests as testing a deprecated feature with a warning note. :pypi:`pytest-describe` - *last release*: Nov 13, 2021, - *status*: 4 - Beta, - *requires*: pytest (>=4.0.0) + *last release*: Apr 09, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest (<8,>=4.6) Describe-style plugin for pytest @@ -3686,49 +3692,49 @@ This list contains 1233 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: pytest (>=7.0) pytest embedded plugin :pypi:`pytest-embedded-arduino` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for Arduino projects :pypi:`pytest-embedded-idf` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for esp-idf project :pypi:`pytest-embedded-jtag` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing with jtag :pypi:`pytest-embedded-qemu` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for qemu, not target chip :pypi:`pytest-embedded-serial` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing serial ports :pypi:`pytest-embedded-serial-esp` - *last release*: Mar 10, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: N/A @@ -3749,7 +3755,7 @@ This list contains 1233 plugins. A pytest plugin that adds emojis to your test result report :pypi:`pytest-emoji-output` - *last release*: Apr 12, 2022, + *last release*: Apr 09, 2023, *status*: 4 - Beta, *requires*: pytest (==7.0.1) @@ -3944,6 +3950,13 @@ This list contains 1233 plugins. This plugin is used to expect multiple assert using pytest framework. + :pypi:`pytest-expect-test` + *last release*: Apr 10, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.5.0) + + A fixture to support expect tests in pytest + :pypi:`pytest-experiments` *last release*: Dec 13, 2021, *status*: 4 - Beta, @@ -4344,7 +4357,7 @@ This list contains 1233 plugins. Run tests in transactions using pytest, Flask, and SQLalchemy. :pypi:`pytest-flexreport` - *last release*: Apr 05, 2023, + *last release*: Apr 15, 2023, *status*: 4 - Beta, *requires*: pytest @@ -4399,6 +4412,13 @@ This list contains 1233 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility + :pypi:`pytest-frappe` + *last release*: Apr 14, 2023, + *status*: 4 - Beta, + *requires*: pytest>=7.0.0 + + Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications + :pypi:`pytest-freezegun` *last release*: Jul 19, 2020, *status*: 4 - Beta, @@ -4602,6 +4622,13 @@ This list contains 1233 plugins. Plugin for pytest that offloads expected outputs to data files + :pypi:`pytest-goldie` + *last release*: Apr 12, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.5.0) + + A plugin to support golden tests with pytest. + :pypi:`pytest-google-chat` *last release*: Mar 27, 2022, *status*: 4 - Beta, @@ -4729,7 +4756,7 @@ This list contains 1233 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 07, 2023, + *last release*: Apr 14, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.2.2) @@ -4876,7 +4903,7 @@ This list contains 1233 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Jan 20, 2023, + *last release*: Apr 12, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0,>=6.0) @@ -5016,7 +5043,7 @@ This list contains 1233 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Feb 09, 2023, + *last release*: Apr 12, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5093,7 +5120,7 @@ This list contains 1233 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-invenio` - *last release*: Mar 24, 2023, + *last release*: Apr 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<7.2.0,>=6) @@ -5274,6 +5301,13 @@ This list contains 1233 plugins. A pytest plugin for testing Jupyter libraries and extensions. + :pypi:`pytest-jupyterhub` + *last release*: Apr 13, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest + + A reusable JupyterHub pytest plugin + :pypi:`pytest-kafka` *last release*: Oct 01, 2022, *status*: N/A, @@ -6044,6 +6078,13 @@ This list contains 1233 plugins. pytest plugin to collect information from tests + :pypi:`pytest-mpiexec` + *last release*: Apr 13, 2023, + *status*: 3 - Alpha, + *requires*: pytest + + pytest plugin for running individual tests with mpiexec + :pypi:`pytest-mpl` *last release*: Jul 23, 2022, *status*: 4 - Beta, @@ -6157,7 +6198,7 @@ This list contains 1233 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Jan 11, 2023, + *last release*: Apr 11, 2023, *status*: N/A, *requires*: pytest (>=3.5.0) @@ -7935,7 +7976,7 @@ This list contains 1233 plugins. :pypi:`pytest-sbase` - *last release*: Mar 28, 2023, + *last release*: Apr 15, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -7984,7 +8025,7 @@ This list contains 1233 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Mar 28, 2023, + *last release*: Apr 15, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8033,7 +8074,7 @@ This list contains 1233 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Feb 24, 2023, + *last release*: Apr 15, 2023, *status*: 3 - Alpha, *requires*: pytest (>=6.2) @@ -8411,7 +8452,7 @@ This list contains 1233 plugins. Pytest plugin for the splinter automation library :pypi:`pytest-split` - *last release*: Apr 22, 2022, + *last release*: Apr 12, 2023, *status*: 4 - Beta, *requires*: pytest (>=5,<8) @@ -8642,9 +8683,9 @@ This list contains 1233 plugins. pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. :pypi:`pytest-sugar` - *last release*: Nov 05, 2022, - *status*: 3 - Alpha, - *requires*: pytest (>=2.9) + *last release*: Apr 10, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=6.2.0) pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). @@ -8697,6 +8738,13 @@ This list contains 1233 plugins. + :pypi:`pytest-tally` + *last release*: Apr 13, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=6.2.5) + + A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. + :pypi:`pytest-tap` *last release*: Oct 27, 2021, *status*: 5 - Production/Stable, From f08184ba209fc127e1c483bf7058830db3fea5be Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Apr 2023 18:21:08 +0300 Subject: [PATCH 025/157] doc: add missing changelog for #10907 --- changelog/10907.improvement.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/10907.improvement.rst diff --git a/changelog/10907.improvement.rst b/changelog/10907.improvement.rst new file mode 100644 index 00000000000..7f011a827d3 --- /dev/null +++ b/changelog/10907.improvement.rst @@ -0,0 +1,5 @@ +When an exception traceback to be displayed is completely filtered out (by mechanisms such as ``__tracebackhide__``, internal frames, and similar), now only the exception string and the following message are shown: + +"All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames.". + +Previously, the last frame of the traceback was shown, even though it was hidden. From 819f5abd731a8d48ea05ca01bd2874d298053977 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Apr 2023 19:15:40 +0300 Subject: [PATCH 026/157] testing: remove usages of testdir that sneaked back in --- testing/acceptance_test.py | 6 +++--- testing/logging/test_reporting.py | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 6b421dde641..4dac2cee33f 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1299,12 +1299,12 @@ def test_no_brokenpipeerror_message(pytester: Pytester) -> None: popen.stderr.close() -def test_function_return_non_none_warning(testdir) -> None: - testdir.makepyfile( +def test_function_return_non_none_warning(pytester: Pytester) -> None: + pytester.makepyfile( """ def test_stuff(): return "something" """ ) - res = testdir.runpytest() + res = pytester.runpytest() res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"]) diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 3cd8599b417..ae2f53277fb 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1167,8 +1167,8 @@ def test_log_file_cli_subdirectories_are_successfully_created( assert result.ret == ExitCode.OK -def test_disable_loggers(testdir): - testdir.makepyfile( +def test_disable_loggers(pytester: Pytester) -> None: + pytester.makepyfile( """ import logging import os @@ -1181,13 +1181,13 @@ def test_logger_propagation(caplog): assert caplog.record_tuples == [('test', 10, 'Visible text!')] """ ) - result = testdir.runpytest("--log-disable=disabled", "-s") + result = pytester.runpytest("--log-disable=disabled", "-s") assert result.ret == ExitCode.OK assert not result.stderr.lines -def test_disable_loggers_does_not_propagate(testdir): - testdir.makepyfile( +def test_disable_loggers_does_not_propagate(pytester: Pytester) -> None: + pytester.makepyfile( """ import logging import os @@ -1205,13 +1205,13 @@ def test_logger_propagation_to_parent(caplog): """ ) - result = testdir.runpytest("--log-disable=parent.child", "-s") + result = pytester.runpytest("--log-disable=parent.child", "-s") assert result.ret == ExitCode.OK assert not result.stderr.lines -def test_log_disabling_works_with_log_cli(testdir): - testdir.makepyfile( +def test_log_disabling_works_with_log_cli(pytester: Pytester) -> None: + pytester.makepyfile( """ import logging disabled_log = logging.getLogger('disabled') @@ -1222,7 +1222,7 @@ def test_log_cli_works(caplog): disabled_log.warning("This string will be suppressed.") """ ) - result = testdir.runpytest( + result = pytester.runpytest( "--log-cli-level=DEBUG", "--log-disable=disabled", ) From 41f57ef95db48be04faea33dd5bd2b414f42a395 Mon Sep 17 00:00:00 2001 From: Alex <59836767+acjreno@users.noreply.github.com> Date: Sun, 16 Apr 2023 16:31:45 -0400 Subject: [PATCH 027/157] Fix `pytrace=False` and `--tb=line` reports `None` (#10905) Closes #10831. This fixes a small bug where running tests that contained `pytest.fail(pytrace=False)` with the `--tb=line` flag set results in an output of "None" in the Failures section of the output, and adds a test to ensure the behavior is correct. --- AUTHORS | 1 + changelog/10831.bugfix.rst | 1 + src/_pytest/_code/code.py | 6 ++---- testing/test_terminal.py | 13 +++++++++++++ 4 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 changelog/10831.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 1aa5265e62e..dee73514a59 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,6 +13,7 @@ Ahn Ki-Wook Akiomi Kamakura Alan Velasco Alessio Izzo +Alex Jones Alexander Johnson Alexander King Alexei Kozlenok diff --git a/changelog/10831.bugfix.rst b/changelog/10831.bugfix.rst new file mode 100644 index 00000000000..ea641dee60e --- /dev/null +++ b/changelog/10831.bugfix.rst @@ -0,0 +1 @@ +Terminal Reporting: Fixed bug when running in ``--tb=line`` mode where ``pytest.fail(pytrace=False)`` tests report ``None``. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 67d1062ff53..5bc78f4788f 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -647,7 +647,7 @@ def getrepr( Ignored if ``style=="native"``. :param str style: - long|short|no|native|value traceback style. + long|short|line|no|native|value traceback style. :param bool abspath: If paths should be changed to absolute or left unchanged. @@ -977,9 +977,7 @@ def repr_excinfo( ) else: reprtraceback = self.repr_traceback(excinfo_) - reprcrash: Optional[ReprFileLocation] = ( - excinfo_._getreprcrash() if self.style != "value" else None - ) + reprcrash = excinfo_._getreprcrash() else: # Fallback to native repr if the exception doesn't have a traceback: # ExceptionInfo objects require a full traceback to work. diff --git a/testing/test_terminal.py b/testing/test_terminal.py index fe325b72d29..97ce2cb5674 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1539,6 +1539,19 @@ def test_func2(): s = result.stdout.str() assert "def test_func2" not in s + def test_tb_crashline_pytrace_false(self, pytester: Pytester, option) -> None: + p = pytester.makepyfile( + """ + import pytest + def test_func1(): + pytest.fail('test_func1', pytrace=False) + """ + ) + result = pytester.runpytest("--tb=line") + result.stdout.str() + bn = p.name + result.stdout.fnmatch_lines(["*%s:3: Failed: test_func1" % bn]) + def test_pytest_report_header(self, pytester: Pytester, option) -> None: pytester.makeconftest( """ From 2d6206b89a78e2fbcf84094e873b13b15ff7929e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 08:55:36 +0200 Subject: [PATCH 028/157] build(deps): Bump pytest-sugar in /testing/plugins_integration (#10922) Bumps [pytest-sugar](https://github.com/Teemu/pytest-sugar) from 0.9.5 to 0.9.7. - [Release notes](https://github.com/Teemu/pytest-sugar/releases) - [Changelog](https://github.com/Teemu/pytest-sugar/blob/main/CHANGES.rst) - [Commits](https://github.com/Teemu/pytest-sugar/commits/v0.9.7) --- updated-dependencies: - dependency-name: pytest-sugar dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 44889c506c2..c3746cba541 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -8,7 +8,7 @@ pytest-flakes==4.0.5 pytest-html==3.2.0 pytest-mock==3.10.0 pytest-rerunfailures==11.1.2 -pytest-sugar==0.9.5 +pytest-sugar==0.9.7 pytest-trio==0.7.0 pytest-twisted==1.14.0 twisted==22.8.0 From 14be71b234a617f487b58a6f277a64c6904b3164 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 07:03:27 +0200 Subject: [PATCH 029/157] [pre-commit.ci] pre-commit autoupdate (#10926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/autoflake: v2.0.2 → v2.1.0](https://github.com/PyCQA/autoflake/compare/v2.0.2...v2.1.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ca20aec29fd..5393fcd157b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: exclude: _pytest/(debugging|hookspec).py language_version: python3 - repo: https://github.com/PyCQA/autoflake - rev: v2.0.2 + rev: v2.1.0 hooks: - id: autoflake name: autoflake From 0860f4e916db4f0b7bae99b9c9f85a02e88ff4d3 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 22 Apr 2023 21:22:25 +0200 Subject: [PATCH 030/157] Add 2024 pytest training (#10933) --- doc/en/index.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 6f3115b19c2..bd4a6486783 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -1,11 +1,10 @@ :orphan: -.. - .. sidebar:: Next Open Trainings +.. sidebar:: Next Open Trainings - - `Professional Testing with Python `_, via `Python Academy `_, March 7th to 9th 2023 (3 day in-depth training), Remote + - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Remote - Also see :doc:`previous talks and blogposts `. + Also see :doc:`previous talks and blogposts `. .. _features: From 15156757b6432669834d5b89810cf9e00f890a2b Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 23 Apr 2023 00:21:26 +0000 Subject: [PATCH 031/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 100 ++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index a6fa69d54f5..40034ec10a8 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1239 plugins. +This list contains 1243 plugins. .. only:: not latex @@ -37,7 +37,7 @@ This list contains 1239 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 04, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 06, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 18, 2023 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -227,7 +227,7 @@ This list contains 1239 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Mar 20, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Apr 20, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -468,7 +468,7 @@ This list contains 1239 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Apr 14, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Apr 17, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Oct 20, 2022 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -517,7 +517,7 @@ This list contains 1239 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 14, 2023 3 - Alpha pytest (==7.2.2) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 22, 2023 3 - Alpha pytest (==7.2.2) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) @@ -537,7 +537,7 @@ This list contains 1239 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest Sep 12, 2022 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Mar 15, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -663,6 +663,7 @@ This list contains 1239 plugins. :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) + :pypi:`pytest-maybe-context` Simplify tests with warning and exception cases. Apr 16, 2023 N/A pytest (>=7,<8) :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) @@ -676,7 +677,7 @@ This list contains 1239 plugins. :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin Apr 06, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Apr 19, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) @@ -723,7 +724,7 @@ This list contains 1239 plugins. :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Apr 11, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Apr 18, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -896,7 +897,7 @@ This list contains 1239 plugins. :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 30, 2023 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Feb 16, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-recordings` Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal Aug 13, 2020 N/A N/A - :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Mar 27, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Apr 19, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -908,12 +909,12 @@ This list contains 1239 plugins. :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Dec 31, 2022 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6) - :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Mar 27, 2023 4 - Beta pytest (>=4.6) + :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 21, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Mar 04, 2020 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 31, 2020 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jun 09, 2021 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Dec 16, 2021 3 - Alpha pytest + :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 08, 2021 4 - Beta N/A @@ -923,7 +924,7 @@ This list contains 1239 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Mar 11, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 28, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Apr 21, 2023 N/A pytest (>=3.8.0) :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -934,7 +935,7 @@ This list contains 1239 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 09, 2023 5 - Production/Stable pytest (>=5.3) :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Nov 29, 2022 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 28, 2023 N/A pytest (~=4.6) ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Apr 20, 2023 N/A pytest (~=4.6) ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 @@ -942,7 +943,9 @@ This list contains 1239 plugins. :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed May 11, 2022 5 - Production/Stable pytest - :pypi:`pytest-result-log` Write the execution result of the case to the log Feb 02, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-result-log` Write the execution result of the case to the log Apr 17, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) @@ -977,14 +980,14 @@ This list contains 1239 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 15, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 21, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 15, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 21, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1055,6 +1058,7 @@ This list contains 1239 plugins. :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) + :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. Apr 19, 2023 4 - Beta pytest (>=6.2.5) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest @@ -1148,7 +1152,7 @@ This list contains 1239 plugins. :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Apr 03, 2022 N/A pytest :pypi:`pytest-tmpfs` A pytest plugin that helps you on using a temporary filesystem for testing. Aug 29, 2022 N/A pytest :pypi:`pytest-tmreport` this is a vue-element ui report for pytest Aug 12, 2022 N/A N/A - :pypi:`pytest-tmux` A pytest plugin that enables tmux driven tests Feb 15, 2023 4 - Beta N/A + :pypi:`pytest-tmux` A pytest plugin that enables tmux driven tests Apr 22, 2023 4 - Beta N/A :pypi:`pytest-todo` A small plugin for the pytest testing framework, marking TODO comments as failure May 23, 2019 4 - Beta pytest :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A @@ -1396,7 +1400,7 @@ This list contains 1239 plugins. :pypi:`pytest-alembic` - *last release*: Apr 06, 2023, + *last release*: Apr 18, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -2726,7 +2730,7 @@ This list contains 1239 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Mar 20, 2023, + *last release*: Apr 20, 2023, *status*: N/A, *requires*: N/A @@ -4413,7 +4417,7 @@ This list contains 1239 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: Apr 14, 2023, + *last release*: Apr 17, 2023, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -4756,7 +4760,7 @@ This list contains 1239 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 14, 2023, + *last release*: Apr 22, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.2.2) @@ -4896,7 +4900,7 @@ This list contains 1239 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Mar 15, 2023, + *last release*: Apr 19, 2023, *status*: N/A, *requires*: pytest (>=7.2.0,<8.0.0) @@ -5777,6 +5781,13 @@ This list contains 1239 plugins. Provide tools for generating tests from combinations of fixtures. + :pypi:`pytest-maybe-context` + *last release*: Apr 16, 2023, + *status*: N/A, + *requires*: pytest (>=7,<8) + + Simplify tests with warning and exception cases. + :pypi:`pytest-maybe-raises` *last release*: May 27, 2022, *status*: N/A, @@ -5869,7 +5880,7 @@ This list contains 1239 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Apr 06, 2023, + *last release*: Apr 19, 2023, *status*: N/A, *requires*: pytest @@ -6198,7 +6209,7 @@ This list contains 1239 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Apr 11, 2023, + *last release*: Apr 18, 2023, *status*: N/A, *requires*: pytest (>=3.5.0) @@ -7409,7 +7420,7 @@ This list contains 1239 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal :pypi:`pytest-redis` - *last release*: Mar 27, 2023, + *last release*: Apr 19, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2) @@ -7493,8 +7504,8 @@ This list contains 1239 plugins. Pytest plugin for controlling remote data access. :pypi:`pytest-remote-response` - *last release*: Mar 27, 2023, - *status*: 4 - Beta, + *last release*: Apr 21, 2023, + *status*: 5 - Production/Stable, *requires*: pytest (>=4.6) Pytest plugin for capturing and mocking connection requests. @@ -7528,7 +7539,7 @@ This list contains 1239 plugins. Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests :pypi:`pytest-repo-health` - *last release*: Dec 16, 2021, + *last release*: Apr 17, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -7598,7 +7609,7 @@ This list contains 1239 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Mar 28, 2023, + *last release*: Apr 21, 2023, *status*: N/A, *requires*: pytest (>=3.8.0) @@ -7675,7 +7686,7 @@ This list contains 1239 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Feb 28, 2023, + *last release*: Apr 20, 2023, *status*: N/A, *requires*: pytest (~=4.6) ; python_version == "2.7" @@ -7731,12 +7742,26 @@ This list contains 1239 plugins. Pytest plugin to restrict the test types allowed :pypi:`pytest-result-log` - *last release*: Feb 02, 2023, + *last release*: Apr 17, 2023, *status*: N/A, *requires*: pytest>=7.2.0 Write the execution result of the case to the log + :pypi:`pytest-result-sender` + *last release*: Apr 20, 2023, + *status*: N/A, + *requires*: pytest>=7.3.1 + + + + :pypi:`pytest-resume` + *last release*: Apr 22, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.0) + + A Pytest plugin to resuming from the last run test + :pypi:`pytest-rethinkdb` *last release*: Jul 24, 2016, *status*: 4 - Beta, @@ -7976,7 +8001,7 @@ This list contains 1239 plugins. :pypi:`pytest-sbase` - *last release*: Apr 15, 2023, + *last release*: Apr 21, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8025,7 +8050,7 @@ This list contains 1239 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Apr 15, 2023, + *last release*: Apr 21, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8521,6 +8546,13 @@ This list contains 1239 plugins. pytest sqlalchemy plugin for mock + :pypi:`pytest-sqlalchemy-session` + *last release*: Apr 19, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=6.2.5) + + A pytest plugin for preserving test isolation that use SQLAlchemy. + :pypi:`pytest-sql-bigquery` *last release*: Dec 19, 2019, *status*: N/A, @@ -9173,7 +9205,7 @@ This list contains 1239 plugins. this is a vue-element ui report for pytest :pypi:`pytest-tmux` - *last release*: Feb 15, 2023, + *last release*: Apr 22, 2023, *status*: 4 - Beta, *requires*: N/A From 158f41fdf8d11afcf01e4e15a9d96d95a3041d77 Mon Sep 17 00:00:00 2001 From: Bryan Ricker <978899+bricker@users.noreply.github.com> Date: Tue, 25 Apr 2023 01:49:16 -0700 Subject: [PATCH 032/157] Fix documentation typo (#10942) --- doc/en/reference/reference.rst | 2 +- src/_pytest/logging.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 963e666ade3..8b42bf12965 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1996,7 +1996,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. --log-disable=LOGGER_DISABLE - Disable a logger by name. Can be passed multipe + Disable a logger by name. Can be passed multiple times. [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 4e3d12475d1..2480a5edd29 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -302,7 +302,7 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs): action="append", default=[], dest="logger_disable", - help="Disable a logger by name. Can be passed multipe times.", + help="Disable a logger by name. Can be passed multiple times.", ) From e03f82c359ee2b6596dbf3aeece8537f4b8fb7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 25 Apr 2023 10:51:10 +0200 Subject: [PATCH 033/157] Filter new pkg_resources deprecations (#10938) Fixes https://github.com/pytest-dev/pytest/issues/10815 --- testing/acceptance_test.py | 8 ++++++-- testing/test_monkeypatch.py | 4 +--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 4dac2cee33f..680afe13391 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -695,11 +695,15 @@ def test_cmdline_python_namespace_package( monkeypatch.chdir("world") # pgk_resources.declare_namespace has been deprecated in favor of implicit namespace packages. + # pgk_resources has been deprecated entirely. # While we could change the test to use implicit namespace packages, seems better # to still ensure the old declaration via declare_namespace still works. - ignore_w = r"-Wignore:Deprecated call to `pkg_resources.declare_namespace" + ignore_w = ( + r"-Wignore:Deprecated call to `pkg_resources.declare_namespace", + r"-Wignore:pkg_resources is deprecated", + ) result = pytester.runpytest( - "--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world", ignore_w + "--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world", *ignore_w ) assert result.ret == 0 result.stdout.fnmatch_lines( diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 3d09ef4263a..500e244531a 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -425,9 +425,7 @@ class A: assert A.x == 1 -@pytest.mark.filterwarnings( - "ignore:Deprecated call to `pkg_resources.declare_namespace" -) +@pytest.mark.filterwarnings(r"ignore:.*\bpkg_resources\b:DeprecationWarning") def test_syspath_prepend_with_namespace_packages( pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: From 3823ce60dd977e55168915306376b98474531eb2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 10:52:15 +0200 Subject: [PATCH 034/157] [pre-commit.ci] pre-commit autoupdate (#10941) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/autoflake: v2.1.0 → v2.1.1](https://github.com/PyCQA/autoflake/compare/v2.1.0...v2.1.1) - [github.com/asottile/pyupgrade: v3.3.1 → v3.3.2](https://github.com/asottile/pyupgrade/compare/v3.3.1...v3.3.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5393fcd157b..e3fdbd58a92 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: exclude: _pytest/(debugging|hookspec).py language_version: python3 - repo: https://github.com/PyCQA/autoflake - rev: v2.1.0 + rev: v2.1.1 hooks: - id: autoflake name: autoflake @@ -44,7 +44,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py37-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.3.2 hooks: - id: pyupgrade args: [--py37-plus] From a15f54496293157b4c8f65164f86ba81c3d908a1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 26 Apr 2023 08:13:06 +0200 Subject: [PATCH 035/157] doc: Fix 2024 training location (#10947) --- 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 bd4a6486783..87213878890 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: Next Open Trainings - - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Remote + - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Leipzig/Remote Also see :doc:`previous talks and blogposts `. From cc23ec91d042ee15145b890aea04e96f6e831101 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 23:17:54 +0300 Subject: [PATCH 036/157] code: stop storing weakref to ExceptionInfo on Traceback and TracebackEntry TracebackEntry needs the excinfo for the `__tracebackhide__ = callback` functionality, where `callback` accepts the excinfo. Currently it achieves this by storing a weakref to the excinfo which created it. I think this is not great, mixing layers and bloating the objects. Instead, have `ishidden` (and transitively, `Traceback.filter()`) take the excinfo as a parameter. --- src/_pytest/_code/code.py | 53 ++++++++++++++++++++---------------- src/_pytest/nodes.py | 2 +- src/_pytest/python.py | 2 +- src/_pytest/unittest.py | 2 +- testing/code/test_excinfo.py | 24 ++++++++-------- testing/python/collect.py | 4 +-- 6 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 5bc78f4788f..26db750e6e8 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -31,7 +31,6 @@ from typing import TYPE_CHECKING from typing import TypeVar from typing import Union -from weakref import ref import pluggy @@ -52,7 +51,6 @@ if TYPE_CHECKING: from typing_extensions import Literal from typing_extensions import SupportsIndex - from weakref import ReferenceType _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] @@ -194,15 +192,13 @@ def getargs(self, var: bool = False): class TracebackEntry: """A single entry in a Traceback.""" - __slots__ = ("_rawentry", "_excinfo", "_repr_style") + __slots__ = ("_rawentry", "_repr_style") def __init__( self, rawentry: TracebackType, - excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None, ) -> None: self._rawentry = rawentry - self._excinfo = excinfo self._repr_style: Optional['Literal["short", "long"]'] = None @property @@ -272,7 +268,7 @@ def getsource( source = property(getsource) - def ishidden(self) -> bool: + def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: """Return True if the current frame has a var __tracebackhide__ resolving to True. @@ -296,7 +292,7 @@ def ishidden(self) -> bool: else: break if tbh and callable(tbh): - return tbh(None if self._excinfo is None else self._excinfo()) + return tbh(excinfo) return tbh def __str__(self) -> str: @@ -329,16 +325,14 @@ class Traceback(List[TracebackEntry]): def __init__( self, tb: Union[TracebackType, Iterable[TracebackEntry]], - excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None, ) -> None: """Initialize from given python traceback object and ExceptionInfo.""" - self._excinfo = excinfo if isinstance(tb, TracebackType): def f(cur: TracebackType) -> Iterable[TracebackEntry]: cur_: Optional[TracebackType] = cur while cur_ is not None: - yield TracebackEntry(cur_, excinfo=excinfo) + yield TracebackEntry(cur_) cur_ = cur_.tb_next super().__init__(f(tb)) @@ -378,7 +372,7 @@ def cut( continue if firstlineno is not None and x.frame.code.firstlineno != firstlineno: continue - return Traceback(x._rawentry, self._excinfo) + return Traceback(x._rawentry) return self @overload @@ -398,25 +392,36 @@ def __getitem__( return super().__getitem__(key) def filter( - self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden() + self, + # TODO(py38): change to positional only. + _excinfo_or_fn: Union[ + "ExceptionInfo[BaseException]", + Callable[[TracebackEntry], bool], + ], ) -> "Traceback": - """Return a Traceback instance with certain items removed + """Return a Traceback instance with certain items removed. - fn is a function that gets a single argument, a TracebackEntry - instance, and should return True when the item should be added - to the Traceback, False when not. + If the filter is an `ExceptionInfo`, removes all the ``TracebackEntry``s + which are hidden (see ishidden() above). - By default this removes all the TracebackEntries which are hidden - (see ishidden() above). + Otherwise, the filter is a function that gets a single argument, a + ``TracebackEntry`` instance, and should return True when the item should + be added to the ``Traceback``, False when not. """ - return Traceback(filter(fn, self), self._excinfo) + if isinstance(_excinfo_or_fn, ExceptionInfo): + fn = lambda x: not x.ishidden(_excinfo_or_fn) # noqa: E731 + else: + fn = _excinfo_or_fn + return Traceback(filter(fn, self)) - def getcrashentry(self) -> Optional[TracebackEntry]: + def getcrashentry( + self, excinfo: Optional["ExceptionInfo[BaseException]"] + ) -> Optional[TracebackEntry]: """Return last non-hidden traceback entry that lead to the exception of a traceback, or None if all hidden.""" for i in range(-1, -len(self) - 1, -1): entry = self[i] - if not entry.ishidden(): + if not entry.ishidden(excinfo): return entry return None @@ -583,7 +588,7 @@ def typename(self) -> str: def traceback(self) -> Traceback: """The traceback.""" if self._traceback is None: - self._traceback = Traceback(self.tb, excinfo=ref(self)) + self._traceback = Traceback(self.tb) return self._traceback @traceback.setter @@ -624,7 +629,7 @@ def errisinstance( def _getreprcrash(self) -> Optional["ReprFileLocation"]: exconly = self.exconly(tryshort=True) - entry = self.traceback.getcrashentry() + entry = self.traceback.getcrashentry(self) if entry is None: return None path, lineno = entry.frame.code.raw.co_filename, entry.lineno @@ -882,7 +887,7 @@ def _makepath(self, path: Union[Path, str]) -> str: def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback": traceback = excinfo.traceback if self.tbfilter: - traceback = traceback.filter() + traceback = traceback.filter(excinfo) if isinstance(excinfo.value, RecursionError): traceback, extraline = self._truncate_recursive_traceback(traceback) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index ea016786e2b..738ab97e996 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -560,7 +560,7 @@ def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: ntraceback = traceback.cut(path=self.path) if ntraceback == traceback: ntraceback = ntraceback.cut(excludepath=tracebackcutdir) - excinfo.traceback = ntraceback.filter() + excinfo.traceback = ntraceback.filter(excinfo) def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d04b6fa4ded..c65c41b97f1 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1814,7 +1814,7 @@ def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: if not ntraceback: ntraceback = traceback - excinfo.traceback = ntraceback.filter() + excinfo.traceback = ntraceback.filter(excinfo) # issue364: mark all but first and last frames to # only show a single-line message for each frame. if self.config.getoption("tbstyle", "auto") == "auto": diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index c660aa75db2..7a5e736610e 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -339,7 +339,7 @@ def _prunetraceback( ) -> None: super()._prunetraceback(excinfo) traceback = excinfo.traceback.filter( - lambda x: not x.frame.f_globals.get("__unittest") + lambda x: not x.frame.f_globals.get("__unittest"), ) if traceback: excinfo.traceback = traceback diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 6a720e64c3f..d0eb5e64655 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -186,7 +186,7 @@ def test_traceback_cut_excludepath(self, pytester: Pytester) -> None: def test_traceback_filter(self): traceback = self.excinfo.traceback - ntraceback = traceback.filter() + ntraceback = traceback.filter(self.excinfo) assert len(ntraceback) == len(traceback) - 1 @pytest.mark.parametrize( @@ -217,7 +217,7 @@ def h(): excinfo = pytest.raises(ValueError, h) traceback = excinfo.traceback - ntraceback = traceback.filter() + ntraceback = traceback.filter(excinfo) print(f"old: {traceback!r}") print(f"new: {ntraceback!r}") @@ -307,7 +307,7 @@ def f(): excinfo = pytest.raises(ValueError, f) tb = excinfo.traceback - entry = tb.getcrashentry() + entry = tb.getcrashentry(excinfo) assert entry is not None co = _pytest._code.Code.from_function(h) assert entry.frame.code.path == co.path @@ -324,7 +324,7 @@ def f(): g() excinfo = pytest.raises(ValueError, f) - assert excinfo.traceback.getcrashentry() is None + assert excinfo.traceback.getcrashentry(excinfo) is None def test_excinfo_exconly(): @@ -626,7 +626,7 @@ def func1(): """ ) excinfo = pytest.raises(ValueError, mod.func1) - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) p = FormattedExcinfo() reprtb = p.repr_traceback_entry(excinfo.traceback[-1]) @@ -659,7 +659,7 @@ def func1(m, x, y, z): """ ) excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120) - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) entry = excinfo.traceback[-1] p = FormattedExcinfo(funcargs=True) reprfuncargs = p.repr_args(entry) @@ -686,7 +686,7 @@ def func1(x, *y, **z): """ ) excinfo = pytest.raises(ValueError, mod.func1, "a", "b", c="d") - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) entry = excinfo.traceback[-1] p = FormattedExcinfo(funcargs=True) reprfuncargs = p.repr_args(entry) @@ -960,7 +960,7 @@ def f(): """ ) excinfo = pytest.raises(ValueError, mod.f) - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) repr = excinfo.getrepr() repr.toterminal(tw_mock) assert tw_mock.lines[0] == "" @@ -994,7 +994,7 @@ def f(): ) excinfo = pytest.raises(ValueError, mod.f) tmp_path.joinpath("mod.py").unlink() - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) repr = excinfo.getrepr() repr.toterminal(tw_mock) assert tw_mock.lines[0] == "" @@ -1026,7 +1026,7 @@ def f(): ) excinfo = pytest.raises(ValueError, mod.f) tmp_path.joinpath("mod.py").write_text("asdf") - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) repr = excinfo.getrepr() repr.toterminal(tw_mock) assert tw_mock.lines[0] == "" @@ -1123,7 +1123,7 @@ def i(): """ ) excinfo = pytest.raises(ValueError, mod.f) - excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback = excinfo.traceback.filter(excinfo) excinfo.traceback[1].set_repr_style("short") excinfo.traceback[2].set_repr_style("short") r = excinfo.getrepr(style="long") @@ -1391,7 +1391,7 @@ def f(): with pytest.raises(TypeError) as excinfo: mod.f() # previously crashed with `AttributeError: list has no attribute get` - excinfo.traceback.filter() + excinfo.traceback.filter(excinfo) @pytest.mark.parametrize("style", ["short", "long"]) diff --git a/testing/python/collect.py b/testing/python/collect.py index ac3edd395ab..41845517bf0 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1003,9 +1003,9 @@ def test_skip_simple(self): with pytest.raises(pytest.skip.Exception) as excinfo: pytest.skip("xxx") assert excinfo.traceback[-1].frame.code.name == "skip" - assert excinfo.traceback[-1].ishidden() + assert excinfo.traceback[-1].ishidden(excinfo) assert excinfo.traceback[-2].frame.code.name == "test_skip_simple" - assert not excinfo.traceback[-2].ishidden() + assert not excinfo.traceback[-2].ishidden(excinfo) def test_traceback_argsetup(self, pytester: Pytester) -> None: pytester.makeconftest( From 0a20452f78a2f5401cf0fc05dad04c8aeee170d7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 23:43:00 +0300 Subject: [PATCH 037/157] code: inline `Traceback.getcrashentry` into `ExceptionInfo._getreprcrash` Since `Traceback.getcrashentry` takes the `ExceptionInfo`, it is not really independent of it and is in the wrong layer. Prevent nonsensical mistakes by inlining it. --- src/_pytest/_code/code.py | 26 +++++++++----------------- testing/code/test_excinfo.py | 18 ++++++++---------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 26db750e6e8..581399949b6 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -414,17 +414,6 @@ def filter( fn = _excinfo_or_fn return Traceback(filter(fn, self)) - def getcrashentry( - self, excinfo: Optional["ExceptionInfo[BaseException]"] - ) -> Optional[TracebackEntry]: - """Return last non-hidden traceback entry that lead to the exception of - a traceback, or None if all hidden.""" - for i in range(-1, -len(self) - 1, -1): - entry = self[i] - if not entry.ishidden(excinfo): - return entry - return None - def recursionindex(self) -> Optional[int]: """Return the index of the frame/TracebackEntry where recursion originates if appropriate, None if no recursion occurred.""" @@ -628,12 +617,15 @@ def errisinstance( return isinstance(self.value, exc) def _getreprcrash(self) -> Optional["ReprFileLocation"]: - exconly = self.exconly(tryshort=True) - entry = self.traceback.getcrashentry(self) - if entry is None: - return None - path, lineno = entry.frame.code.raw.co_filename, entry.lineno - return ReprFileLocation(path, lineno + 1, exconly) + # Find last non-hidden traceback entry that led to the exception of the + # traceback, or None if all hidden. + for i in range(-1, -len(self.traceback) - 1, -1): + entry = self.traceback[i] + if not entry.ishidden(self): + path, lineno = entry.frame.code.raw.co_filename, entry.lineno + exconly = self.exconly(tryshort=True) + return ReprFileLocation(path, lineno + 1, exconly) + return None def getrepr( self, diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index d0eb5e64655..3b05390be3a 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -11,7 +11,7 @@ from typing import TYPE_CHECKING from typing import Union -import _pytest +import _pytest._code import pytest from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionInfo @@ -290,7 +290,7 @@ def fail(): excinfo = pytest.raises(ValueError, fail) assert excinfo.traceback.recursionindex() is None - def test_traceback_getcrashentry(self): + def test_getreprcrash(self): def i(): __tracebackhide__ = True raise ValueError @@ -306,15 +306,13 @@ def f(): g() excinfo = pytest.raises(ValueError, f) - tb = excinfo.traceback - entry = tb.getcrashentry(excinfo) - assert entry is not None + reprcrash = excinfo._getreprcrash() + assert reprcrash is not None co = _pytest._code.Code.from_function(h) - assert entry.frame.code.path == co.path - assert entry.lineno == co.firstlineno + 1 - assert entry.frame.code.name == "h" + assert reprcrash.path == str(co.path) + assert reprcrash.lineno == co.firstlineno + 1 + 1 - def test_traceback_getcrashentry_empty(self): + def test_getreprcrash_empty(self): def g(): __tracebackhide__ = True raise ValueError @@ -324,7 +322,7 @@ def f(): g() excinfo = pytest.raises(ValueError, f) - assert excinfo.traceback.getcrashentry(excinfo) is None + assert excinfo._getreprcrash() is None def test_excinfo_exconly(): From 6f7f89f3c42861448a370fe7bfc343083850f600 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 12 Apr 2023 22:58:57 +0300 Subject: [PATCH 038/157] code: make TracebackEntry immutable TracebackEntry being mutable caught me by surprise and makes reasoning about the exception formatting code harder. Make it a proper value. --- src/_pytest/_code/code.py | 15 +++++++++------ src/_pytest/python.py | 9 +++++++-- testing/code/test_excinfo.py | 6 ++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 581399949b6..5148dcdbeb4 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -49,6 +49,7 @@ from _pytest.pathlib import bestrelpath if TYPE_CHECKING: + from typing_extensions import Final from typing_extensions import Literal from typing_extensions import SupportsIndex @@ -197,18 +198,20 @@ class TracebackEntry: def __init__( self, rawentry: TracebackType, + repr_style: Optional['Literal["short", "long"]'] = None, ) -> None: - self._rawentry = rawentry - self._repr_style: Optional['Literal["short", "long"]'] = None + self._rawentry: "Final" = rawentry + self._repr_style: "Final" = repr_style + + def with_repr_style( + self, repr_style: Optional['Literal["short", "long"]'] + ) -> "TracebackEntry": + return TracebackEntry(self._rawentry, repr_style) @property def lineno(self) -> int: return self._rawentry.tb_lineno - 1 - def set_repr_style(self, mode: "Literal['short', 'long']") -> None: - assert mode in ("short", "long") - self._repr_style = mode - @property def frame(self) -> Frame: return Frame(self._rawentry.tb_frame) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c65c41b97f1..8ed6b46dfc4 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -35,6 +35,7 @@ from _pytest._code import getfslineno from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr +from _pytest._code.code import Traceback from _pytest._io import TerminalWriter from _pytest._io.saferepr import saferepr from _pytest.compat import ascii_escaped @@ -1819,8 +1820,12 @@ def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: # only show a single-line message for each frame. if self.config.getoption("tbstyle", "auto") == "auto": if len(excinfo.traceback) > 2: - for entry in excinfo.traceback[1:-1]: - entry.set_repr_style("short") + excinfo.traceback = Traceback( + entry + if i == 0 or i == len(excinfo.traceback) - 1 + else entry.with_repr_style("short") + for i, entry in enumerate(excinfo.traceback) + ) # TODO: Type ignored -- breaks Liskov Substitution. def repr_failure( # type: ignore[override] diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 3b05390be3a..bda6cd4cdd0 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1122,8 +1122,10 @@ def i(): ) excinfo = pytest.raises(ValueError, mod.f) excinfo.traceback = excinfo.traceback.filter(excinfo) - excinfo.traceback[1].set_repr_style("short") - excinfo.traceback[2].set_repr_style("short") + excinfo.traceback = _pytest._code.Traceback( + entry if i not in (1, 2) else entry.with_repr_style("short") + for i, entry in enumerate(excinfo.traceback) + ) r = excinfo.getrepr(style="long") r.toterminal(tw_mock) for line in tw_mock.lines: From fcada1ea4763c0e3471cd58ac4b89e7c874e6264 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 13 Apr 2023 13:48:44 +0300 Subject: [PATCH 039/157] nodes: change _prunetraceback to return the new traceback instead of modifying excinfo This makes it usable as a general function, and just more understandable in general. --- src/_pytest/nodes.py | 12 +++++++----- src/_pytest/python.py | 15 +++++++++------ src/_pytest/unittest.py | 13 +++++++------ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 738ab97e996..1a1a47a28d4 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -22,6 +22,7 @@ from _pytest._code import getfslineno from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr +from _pytest._code.code import Traceback from _pytest.compat import cached_property from _pytest.compat import LEGACY_PATH from _pytest.config import Config @@ -432,8 +433,8 @@ def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]: assert current is None or isinstance(current, cls) return current - def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: - pass + def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: + return excinfo.traceback def _repr_failure_py( self, @@ -452,7 +453,7 @@ def _repr_failure_py( if self.config.getoption("fulltrace", False): style = "long" else: - self._prunetraceback(excinfo) + excinfo.traceback = self._traceback_filter(excinfo) if style == "auto": style = "long" # XXX should excinfo.getrepr record all data and toterminal() process it? @@ -554,13 +555,14 @@ def repr_failure( # type: ignore[override] return self._repr_failure_py(excinfo, style=tbstyle) - def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: + def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: if hasattr(self, "path"): traceback = excinfo.traceback ntraceback = traceback.cut(path=self.path) if ntraceback == traceback: ntraceback = ntraceback.cut(excludepath=tracebackcutdir) - excinfo.traceback = ntraceback.filter(excinfo) + return excinfo.traceback.filter(excinfo) + return excinfo.traceback def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 8ed6b46dfc4..ae09da48e66 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1802,7 +1802,7 @@ def runtest(self) -> None: def setup(self) -> None: self._request._fillfixtures() - def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: + def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False): code = _pytest._code.Code.from_function(get_real_func(self.obj)) path, firstlineno = code.path, code.firstlineno @@ -1814,19 +1814,22 @@ def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None: ntraceback = ntraceback.filter(filter_traceback) if not ntraceback: ntraceback = traceback + ntraceback = ntraceback.filter(excinfo) - excinfo.traceback = ntraceback.filter(excinfo) # issue364: mark all but first and last frames to # only show a single-line message for each frame. if self.config.getoption("tbstyle", "auto") == "auto": - if len(excinfo.traceback) > 2: - excinfo.traceback = Traceback( + if len(ntraceback) > 2: + ntraceback = Traceback( entry - if i == 0 or i == len(excinfo.traceback) - 1 + if i == 0 or i == len(ntraceback) - 1 else entry.with_repr_style("short") - for i, entry in enumerate(excinfo.traceback) + for i, entry in enumerate(ntraceback) ) + return ntraceback + return excinfo.traceback + # TODO: Type ignored -- breaks Liskov Substitution. def repr_failure( # type: ignore[override] self, diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 7a5e736610e..d42a12a3a9e 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -334,15 +334,16 @@ def runtest(self) -> None: finally: delattr(self._testcase, self.name) - def _prunetraceback( + def _traceback_filter( self, excinfo: _pytest._code.ExceptionInfo[BaseException] - ) -> None: - super()._prunetraceback(excinfo) - traceback = excinfo.traceback.filter( + ) -> _pytest._code.Traceback: + traceback = super()._traceback_filter(excinfo) + ntraceback = traceback.filter( lambda x: not x.frame.f_globals.get("__unittest"), ) - if traceback: - excinfo.traceback = traceback + if not ntraceback: + ntraceback = traceback + return ntraceback @hookimpl(tryfirst=True) From 725de3a0d3bb3554cb987940561276d5e76c828c Mon Sep 17 00:00:00 2001 From: Sergey Kim <112421728+sergkim13@users.noreply.github.com> Date: Fri, 28 Apr 2023 23:47:47 +0300 Subject: [PATCH 040/157] add flake8-pytest-style mention to goodpractices (#10939) --- doc/en/explanation/goodpractices.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index 7331a789600..efde420cd8f 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -294,3 +294,20 @@ See also `pypa/setuptools#1684 ` setuptools intends to `remove the test command `_. + +Checking with flake8-pytest-style +--------------------------------- + +In order to ensure that pytest is being used correctly in your project, +it can be helpful to use the `flake8-pytest-style `_ flake8 plugin. + +flake8-pytest-style checks for common mistakes and coding style violations in pytest code, +such as incorrect use of fixtures, test function names, and markers. +By using this plugin, you can catch these errors early in the development process +and ensure that your pytest code is consistent and easy to maintain. + +A list of the lints detected by flake8-pytest-style can be found on its `PyPI page `_. + +.. note:: + + flake8-pytest-style is not an official pytest project. Some of the rules enforce certain style choices, such as using `@pytest.fixture()` over `@pytest.fixture`, but you can configure the plugin to fit your preferred style. From 762bb61562d1300eedeb80be2ec2fb8150b3cc3f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 29 Apr 2023 11:37:22 +0300 Subject: [PATCH 041/157] Fix couple of EncodingWarnings (#10954) * faulthandler: fix an EncodingWarning * _py/path: tiny change to `ensure` to silence EncodingWarning We're not supposed to diverge here, but make this change to fix an unavoidable EncodingWarning that is otherwise raised in pytest's test suite. The behavior should be exactly the same besides the warning, hopefully that won't cause confusion. --- src/_pytest/_py/path.py | 2 +- src/_pytest/faulthandler.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index fb64830f814..73a070d19a8 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -953,7 +953,7 @@ def ensure(self, *args, **kwargs): else: p.dirpath()._ensuredirs() if not p.check(file=1): - p.open("w").close() + p.open("wb").close() return p @overload diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index b9c925582ca..ed29346babd 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -27,7 +27,9 @@ def pytest_configure(config: Config) -> None: import faulthandler stderr_fd_copy = os.dup(get_stderr_fileno()) - config.stash[fault_handler_stderr_key] = open(stderr_fd_copy, "w") + config.stash[fault_handler_stderr_key] = open( + stderr_fd_copy, "w", encoding=sys.stderr.encoding + ) config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled() faulthandler.enable(file=config.stash[fault_handler_stderr_key]) From be774667c2313debfa87d4ecd17455d20a4e6187 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 30 Apr 2023 00:23:40 +0000 Subject: [PATCH 042/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 82 ++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 40034ec10a8..db43f072367 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1243 plugins. +This list contains 1247 plugins. .. only:: not latex @@ -457,7 +457,7 @@ This list contains 1243 plugins. :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Feb 27, 2021 5 - Production/Stable pytest (>=5.2) - :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Feb 10, 2023 4 - Beta pytest (~=7.2) + :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Apr 25, 2023 4 - Beta pytest (~=7.3) :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest @@ -520,6 +520,7 @@ This list contains 1243 plugins. :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 22, 2023 3 - Alpha pytest (==7.2.2) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A + :pypi:`pytest-hot-reloading` A pytest plugin to enable a hot reloading daemon. Apr 23, 2023 N/A N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) @@ -595,7 +596,7 @@ This list contains 1243 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 30, 2023 4 - Beta pytest - :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 13, 2023 5 - Production/Stable pytest + :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Oct 01, 2022 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) @@ -752,7 +753,7 @@ This list contains 1243 plugins. :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 Apr 03, 2023 N/A N/A + :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 Apr 24, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A @@ -785,6 +786,7 @@ This list contains 1243 plugins. :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A :pypi:`pytest-passrunner` Pytest plugin providing the 'run_on_pass' marker Feb 10, 2021 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-paste-config` Allow setting the path to a paste config file Sep 18, 2013 3 - Alpha N/A + :pypi:`pytest-patch` An automagic \`patch\` fixture that can patch objects directly or by name. Apr 29, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-patches` A contextmanager pytest fixture for handling multiple mock patches Aug 30, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-pdb` pytest plugin which adds pdb helper commands related to pytest. Jul 31, 2018 N/A N/A :pypi:`pytest-peach` pytest plugin for fuzzing with Peach API Security Apr 12, 2019 4 - Beta pytest (>=2.8.7) @@ -809,7 +811,7 @@ This list contains 1243 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Mar 10, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4) :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -909,7 +911,7 @@ This list contains 1243 plugins. :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Dec 31, 2022 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6) - :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 21, 2023 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Mar 04, 2020 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 31, 2020 5 - Production/Stable pytest (>=3.6) @@ -921,7 +923,7 @@ This list contains 1243 plugins. :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Mar 11, 2023 3 - Alpha pytest + :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Apr 26, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Apr 21, 2023 N/A pytest (>=3.8.0) @@ -934,7 +936,7 @@ This list contains 1243 plugins. :pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6) :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 09, 2023 5 - Production/Stable pytest (>=5.3) :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A - :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Nov 29, 2022 4 - Beta pytest + :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Apr 20, 2023 N/A pytest (~=4.6) ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) @@ -949,6 +951,7 @@ This list contains 1243 plugins. :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) + :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. May 11, 2022 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) @@ -963,7 +966,7 @@ This list contains 1243 plugins. :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Mar 22, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Apr 28, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' @@ -980,14 +983,14 @@ This list contains 1243 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 21, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 29, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 21, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 29, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1058,7 +1061,7 @@ This list contains 1243 plugins. :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) - :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. Apr 19, 2023 4 - Beta pytest (>=6.2.5) + :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. Apr 29, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest @@ -1083,6 +1086,7 @@ This list contains 1243 plugins. :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Feb 16, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Aug 29, 2017 N/A N/A :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) @@ -4340,9 +4344,9 @@ This list contains 1243 plugins. A set of py.test fixtures to test Flask applications. :pypi:`pytest-flask-ligand` - *last release*: Feb 10, 2023, + *last release*: Apr 25, 2023, *status*: 4 - Beta, - *requires*: pytest (~=7.2) + *requires*: pytest (~=7.3) Pytest fixtures and helper functions to use for testing flask-ligand microservices. @@ -4780,6 +4784,13 @@ This list contains 1243 plugins. Report on tests that honor constraints, and guard against regressions + :pypi:`pytest-hot-reloading` + *last release*: Apr 23, 2023, + *status*: N/A, + *requires*: N/A + + A pytest plugin to enable a hot reloading daemon. + :pypi:`pytest-hot-test` *last release*: Dec 10, 2022, *status*: 4 - Beta, @@ -5306,7 +5317,7 @@ This list contains 1243 plugins. A pytest plugin for testing Jupyter libraries and extensions. :pypi:`pytest-jupyterhub` - *last release*: Apr 13, 2023, + *last release*: Apr 25, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6405,7 +6416,7 @@ This list contains 1243 plugins. :pypi:`pytest-ogsm-plugin` - *last release*: Apr 03, 2023, + *last release*: Apr 24, 2023, *status*: N/A, *requires*: N/A @@ -6635,6 +6646,13 @@ This list contains 1243 plugins. Allow setting the path to a paste config file + :pypi:`pytest-patch` + *last release*: Apr 29, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0) + + An automagic \`patch\` fixture that can patch objects directly or by name. + :pypi:`pytest-patches` *last release*: Aug 30, 2021, *status*: 4 - Beta, @@ -6804,7 +6822,7 @@ This list contains 1243 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Mar 10, 2023, + *last release*: Apr 24, 2023, *status*: N/A, *requires*: pytest (<8.0.0,>=6.2.4) @@ -7504,7 +7522,7 @@ This list contains 1243 plugins. Pytest plugin for controlling remote data access. :pypi:`pytest-remote-response` - *last release*: Apr 21, 2023, + *last release*: Apr 26, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=4.6) @@ -7588,7 +7606,7 @@ This list contains 1243 plugins. A plugin to report summarized results in a table format :pypi:`pytest-reportlog` - *last release*: Mar 11, 2023, + *last release*: Apr 26, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -7679,7 +7697,7 @@ This list contains 1243 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: Nov 29, 2022, + *last release*: Apr 26, 2023, *status*: 4 - Beta, *requires*: pytest @@ -7783,6 +7801,13 @@ This list contains 1243 plugins. A pytest plugin to rerun entire class on failure + :pypi:`pytest-reusable-testcases` + *last release*: Apr 28, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-reverse` *last release*: May 11, 2022, *status*: 5 - Production/Stable, @@ -7882,7 +7907,7 @@ This list contains 1243 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Mar 22, 2023, + *last release*: Apr 28, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8001,7 +8026,7 @@ This list contains 1243 plugins. :pypi:`pytest-sbase` - *last release*: Apr 21, 2023, + *last release*: Apr 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8050,7 +8075,7 @@ This list contains 1243 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Apr 21, 2023, + *last release*: Apr 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8547,9 +8572,9 @@ This list contains 1243 plugins. pytest sqlalchemy plugin for mock :pypi:`pytest-sqlalchemy-session` - *last release*: Apr 19, 2023, + *last release*: Apr 29, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.2.5) + *requires*: pytest (>=7.0) A pytest plugin for preserving test isolation that use SQLAlchemy. @@ -8721,6 +8746,13 @@ This list contains 1243 plugins. pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). + :pypi:`pytest-suitemanager` + *last release*: Apr 28, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A simple plugin to use with pytest + :pypi:`pytest-svn` *last release*: May 28, 2019, *status*: 5 - Production/Stable, From 7d548c38e26398d40e5891b3529a8d1eb72e0d74 Mon Sep 17 00:00:00 2001 From: Brian Larsen Date: Sat, 6 May 2023 10:15:11 -0500 Subject: [PATCH 043/157] Improve verbose output by wrapping skip/xfail reasons with margin (#10958) Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/10940.improvement.rst | 3 +++ src/_pytest/terminal.py | 25 ++++++++++++++++++++++++- testing/test_terminal.py | 14 ++++++++------ 4 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 changelog/10940.improvement.rst diff --git a/AUTHORS b/AUTHORS index dee73514a59..438be759814 100644 --- a/AUTHORS +++ b/AUTHORS @@ -56,6 +56,7 @@ Benjamin Peterson Bernard Pratz Bob Ippolito Brian Dorsey +Brian Larsen Brian Maissy Brian Okken Brianna Laugher diff --git a/changelog/10940.improvement.rst b/changelog/10940.improvement.rst new file mode 100644 index 00000000000..f3e33cbc68d --- /dev/null +++ b/changelog/10940.improvement.rst @@ -0,0 +1,3 @@ +Improved verbose output (``-vv``) of ``skip`` and ``xfail`` reasons by performing text wrapping while leaving a clear margin for progress output. + +Added :func:`TerminalReporter.wrap_write() ` as a helper for that. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index dfc0fa98e18..b7793d398ce 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -8,6 +8,7 @@ import inspect import platform import sys +import textwrap import warnings from collections import Counter from functools import partial @@ -426,6 +427,28 @@ def ensure_newline(self) -> None: self._tw.line() self.currentfspath = None + def wrap_write( + self, + content: str, + *, + flush: bool = False, + margin: int = 8, + line_sep: str = "\n", + **markup: bool, + ) -> None: + """Wrap message with margin for progress info.""" + width_of_current_line = self._tw.width_of_current_line + wrapped = line_sep.join( + textwrap.wrap( + " " * width_of_current_line + content, + width=self._screen_width - margin, + drop_whitespace=True, + replace_whitespace=False, + ), + ) + wrapped = wrapped[width_of_current_line:] + self._tw.write(wrapped, flush=flush, **markup) + def write(self, content: str, *, flush: bool = False, **markup: bool) -> None: self._tw.write(content, flush=flush, **markup) @@ -572,7 +595,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: formatted_reason = f" ({reason})" if reason and formatted_reason is not None: - self._tw.write(formatted_reason) + self.wrap_write(formatted_reason) if self._show_progress_info: self._write_progress_information_filling_space() else: diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 97ce2cb5674..c0acb600608 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -387,13 +387,13 @@ def test_10(): pytest.xfail("It's 🕙 o'clock") @pytest.mark.skip( - reason="cannot do foobar because baz is missing due to I don't know what" + reason="1 cannot do foobar because baz is missing due to I don't know what" ) def test_long_skip(): pass @pytest.mark.xfail( - reason="cannot do foobar because baz is missing due to I don't know what" + reason="2 cannot do foobar because baz is missing due to I don't know what" ) def test_long_xfail(): print(1 / 0) @@ -417,8 +417,8 @@ def test_long_xfail(): result.stdout.fnmatch_lines( common_output + [ - "test_verbose_skip_reason.py::test_long_skip SKIPPED (cannot *...) *", - "test_verbose_skip_reason.py::test_long_xfail XFAIL (cannot *...) *", + "test_verbose_skip_reason.py::test_long_skip SKIPPED (1 cannot *...) *", + "test_verbose_skip_reason.py::test_long_xfail XFAIL (2 cannot *...) *", ] ) @@ -428,12 +428,14 @@ def test_long_xfail(): + [ ( "test_verbose_skip_reason.py::test_long_skip SKIPPED" - " (cannot do foobar because baz is missing due to I don't know what) *" + " (1 cannot do foobar" ), + "because baz is missing due to I don't know what) *", ( "test_verbose_skip_reason.py::test_long_xfail XFAIL" - " (cannot do foobar because baz is missing due to I don't know what) *" + " (2 cannot do foobar" ), + "because baz is missing due to I don't know what) *", ] ) From 6514041a351a2fd370a24358bf8f6644ac18789f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 03:56:49 +0000 Subject: [PATCH 044/157] build(deps): Bump django in /testing/plugins_integration Bumps [django](https://github.com/django/django) from 4.2 to 4.2.1. - [Commits](https://github.com/django/django/compare/4.2...4.2.1) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index c3746cba541..bcc3ad9877c 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.6.2 -django==4.2 +django==4.2.1 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 pytest-cov==4.0.0 From 62320e4ff77af1e50cc93cd664a7549ae08338b7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 11:22:50 +0200 Subject: [PATCH 045/157] [pre-commit.ci] pre-commit autoupdate (#10975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - https://github.com/asottile/reorder_python_imports → https://github.com/asottile/reorder-python-imports - [github.com/asottile/pyupgrade: v3.3.2 → v3.4.0](https://github.com/asottile/pyupgrade/compare/v3.3.2...v3.4.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3fdbd58a92..ce621360ed5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,13 +38,13 @@ repos: additional_dependencies: - flake8-typing-imports==1.12.0 - flake8-docstrings==1.5.0 -- repo: https://github.com/asottile/reorder_python_imports +- repo: https://github.com/asottile/reorder-python-imports rev: v3.9.0 hooks: - id: reorder-python-imports args: ['--application-directories=.:src', --py37-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 + rev: v3.4.0 hooks: - id: pyupgrade args: [--py37-plus] From a88ae8289cd21d39dd360666bb2e83dfa98b215e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 19:05:13 -0300 Subject: [PATCH 046/157] [automated] Update plugin list (#10968) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 136 +++++++++++++++++++------------ 1 file changed, 84 insertions(+), 52 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index db43f072367..66b7beb138b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1247 plugins. +This list contains 1251 plugins. .. only:: not latex @@ -30,11 +30,12 @@ This list contains 1247 plugins. :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A + :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Feb 12, 2022 4 - Beta pytest (>=6.1.0) :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-aiomoto` pytest-aiomoto Nov 09, 2022 N/A pytest (>=7.0,<8.0) :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 04, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 18, 2023 N/A pytest (>=6.0) @@ -49,7 +50,7 @@ This list contains 1247 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for py.test to simplify calling ansible modules from tests or fixtures Apr 14, 2023 5 - Production/Stable pytest (<8.0.0,>=6) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 05, 2023 5 - Production/Stable pytest (<8.0.0,>=6) :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -261,7 +262,7 @@ This list contains 1247 plugins. :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 08, 2023 5 - Production/Stable pytest - :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Oct 10, 2022 5 - Production/Stable N/A + :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files May 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A @@ -269,7 +270,7 @@ This list contains 1247 plugins. :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. Mar 01, 2023 N/A pytest (>=6.2.5) ; extra == 'test' + :pypi:`pytest-dbt-core` Pytest extension for dbt. May 03, 2023 N/A pytest (>=6.2.5) ; extra == 'test' :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A @@ -322,7 +323,7 @@ This list contains 1247 plugins. :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) - :pypi:`pytest-docker-fixtures` pytest docker fixtures Mar 24, 2023 3 - Alpha pytest + :pypi:`pytest-docker-fixtures` pytest docker fixtures May 02, 2023 3 - Alpha pytest :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest @@ -392,7 +393,7 @@ This list contains 1247 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Mar 26, 2023 4 - Beta pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. May 05, 2023 4 - Beta pytest>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jan 31, 2022 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -468,7 +469,7 @@ This list contains 1247 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Apr 17, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Oct 20, 2022 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -490,7 +491,7 @@ This list contains 1247 plugins. :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A - :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions Dec 19, 2022 N/A pytest (>=4.0.0) + :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A @@ -517,7 +518,7 @@ This list contains 1247 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 22, 2023 3 - Alpha pytest (==7.2.2) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 06, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` A pytest plugin to enable a hot reloading daemon. Apr 23, 2023 N/A N/A @@ -570,6 +571,7 @@ This list contains 1247 plugins. :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0) :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 01, 2023 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 13, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A @@ -646,7 +648,7 @@ This list contains 1247 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Mar 09, 2023 5 - Production/Stable pytest (==7.2.1) + :pypi:`pytest-logikal` Common testing environment May 05, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -669,6 +671,7 @@ This list contains 1247 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Aug 06, 2022 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Dec 02, 2022 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) @@ -678,7 +681,7 @@ This list contains 1247 plugins. :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin Apr 19, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin May 04, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) @@ -691,7 +694,7 @@ This list contains 1247 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Mar 03, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 03, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -719,7 +722,7 @@ This list contains 1247 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Oct 26, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins May 05, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) @@ -746,7 +749,7 @@ This list contains 1247 plugins. :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 20, 2022 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-oar` PyTest plugin for the OAR testing framework Apr 04, 2023 N/A pytest>=6.0.1 + :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odoo` py.test plugin to run Odoo tests Nov 17, 2022 4 - Beta pytest (>=7.2.0) @@ -796,7 +799,7 @@ This list contains 1247 plugins. :pypi:`pytest-perf` pytest-perf Jun 23, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects Mar 28, 2023 N/A N/A - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Sep 19, 2022 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-picked` Run the tests related to the changed files Dec 23, 2020 N/A pytest (>=3.5.0) @@ -871,7 +874,7 @@ This list contains 1247 plugins. :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvista` Pytest-pyvista package Mar 19, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Apr 07, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 02, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 26, 2022 5 - Production/Stable pytest (>=6.2.3) @@ -937,7 +940,7 @@ This list contains 1247 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 09, 2023 5 - Production/Stable pytest (>=5.3) :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Apr 20, 2023 N/A pytest (~=4.6) ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest May 05, 2023 N/A pytest (~=4.6) ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 @@ -983,14 +986,14 @@ This list contains 1247 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 03, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 03, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1029,6 +1032,7 @@ This list contains 1247 plugins. :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest + :pypi:`pytest-smtpd` package_description May 05, 2023 N/A pytest :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) @@ -1061,7 +1065,7 @@ This list contains 1247 plugins. :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) - :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. Apr 29, 2023 4 - Beta pytest (>=7.0) + :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 05, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest @@ -1109,13 +1113,13 @@ This list contains 1247 plugins. :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. Feb 21, 2022 5 - Production/Stable pytest + :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest :pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures Dec 01, 2022 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods Apr 06, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods May 02, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5) @@ -1354,6 +1358,13 @@ This list contains 1247 plugins. pytest fixtures for writing aiofiles tests with pyfakefs + :pypi:`pytest-aiogram` + *last release*: May 06, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-aiohttp` *last release*: Feb 12, 2022, *status*: 4 - Beta, @@ -1383,9 +1394,9 @@ This list contains 1247 plugins. py.test integration for aioresponses :pypi:`pytest-aioworkers` - *last release*: Dec 04, 2019, - *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *last release*: May 01, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest>=6.1.0 A plugin to test aioworkers project with pytest @@ -1488,11 +1499,11 @@ This list contains 1247 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Apr 14, 2023, + *last release*: May 05, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0.0,>=6) - Plugin for py.test to simplify calling ansible modules from tests or fixtures + Plugin for pytest to simplify calling ansible modules from tests or fixtures :pypi:`pytest-ansible-playbook` *last release*: Mar 08, 2019, @@ -2972,7 +2983,7 @@ This list contains 1247 plugins. A py.test plugin recording and comparing test output. :pypi:`pytest-dataset` - *last release*: Oct 10, 2022, + *last release*: May 01, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3028,7 +3039,7 @@ This list contains 1247 plugins. A pytest plugin for linting a dbt project's conventions :pypi:`pytest-dbt-core` - *last release*: Mar 01, 2023, + *last release*: May 03, 2023, *status*: N/A, *requires*: pytest (>=6.2.5) ; extra == 'test' @@ -3399,7 +3410,7 @@ This list contains 1247 plugins. A plugin to use docker databases for pytests :pypi:`pytest-docker-fixtures` - *last release*: Mar 24, 2023, + *last release*: May 02, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -3889,7 +3900,7 @@ This list contains 1247 plugins. Applies eventlet monkey-patch as a pytest plugin. :pypi:`pytest-examples` - *last release*: Mar 26, 2023, + *last release*: May 05, 2023, *status*: 4 - Beta, *requires*: pytest>=7 @@ -4421,7 +4432,7 @@ This list contains 1247 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: Apr 17, 2023, + *last release*: May 03, 2023, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -4575,8 +4586,8 @@ This list contains 1247 plugins. Plugin for py.test that associates tests with github issues using a marker. :pypi:`pytest-github-actions-annotate-failures` - *last release*: Dec 19, 2022, - *status*: N/A, + *last release*: May 04, 2023, + *status*: 5 - Production/Stable, *requires*: pytest (>=4.0.0) pytest plugin to annotate failed tests with a workflow command for GitHub Actions @@ -4764,9 +4775,9 @@ This list contains 1247 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 22, 2023, + *last release*: May 06, 2023, *status*: 3 - Alpha, - *requires*: pytest (==7.2.2) + *requires*: pytest (==7.3.1) Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5134,6 +5145,13 @@ This list contains 1247 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. + :pypi:`pytest-interface-tester` + *last release*: May 01, 2023, + *status*: 4 - Beta, + *requires*: pytest + + Pytest plugin for checking charm relation interface protocol compliance. + :pypi:`pytest-invenio` *last release*: Apr 13, 2023, *status*: 5 - Production/Stable, @@ -5667,9 +5685,9 @@ This list contains 1247 plugins. :pypi:`pytest-logikal` - *last release*: Mar 09, 2023, + *last release*: May 05, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (==7.2.1) + *requires*: pytest (==7.3.1) Common testing environment @@ -5827,6 +5845,13 @@ This list contains 1247 plugins. A pytest plugin to make a test results report with Markdown table format. + :pypi:`pytest-memlog` + *last release*: May 03, 2023, + *status*: N/A, + *requires*: pytest (>=7.3.0,<8.0.0) + + Log memory usage during tests + :pypi:`pytest-memprof` *last release*: Mar 29, 2019, *status*: 4 - Beta, @@ -5891,7 +5916,7 @@ This list contains 1247 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Apr 19, 2023, + *last release*: May 04, 2023, *status*: N/A, *requires*: pytest @@ -5982,7 +6007,7 @@ This list contains 1247 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Mar 03, 2023, + *last release*: May 03, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6178,9 +6203,9 @@ This list contains 1247 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Oct 26, 2022, + *last release*: May 05, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.0.0) + *requires*: pytest (>=6.2.0) pytest plugin for writing tests for mypy plugins @@ -6367,7 +6392,7 @@ This list contains 1247 plugins. A pytest plugin for generating NUnit3 test result XML output :pypi:`pytest-oar` - *last release*: Apr 04, 2023, + *last release*: May 02, 2023, *status*: N/A, *requires*: pytest>=6.0.1 @@ -6717,7 +6742,7 @@ This list contains 1247 plugins. Pytest tool for persistent objects :pypi:`pytest-pg` - *last release*: Sep 19, 2022, + *last release*: May 04, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.0.0) @@ -7242,7 +7267,7 @@ This list contains 1247 plugins. Pytest-pyvista package :pypi:`pytest-qaseio` - *last release*: Apr 07, 2023, + *last release*: May 02, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.2.2,<8.0.0) @@ -7704,7 +7729,7 @@ This list contains 1247 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Apr 20, 2023, + *last release*: May 05, 2023, *status*: N/A, *requires*: pytest (~=4.6) ; python_version == "2.7" @@ -8026,7 +8051,7 @@ This list contains 1247 plugins. :pypi:`pytest-sbase` - *last release*: Apr 29, 2023, + *last release*: May 03, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8075,7 +8100,7 @@ This list contains 1247 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Apr 29, 2023, + *last release*: May 03, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8347,6 +8372,13 @@ This list contains 1247 plugins. Send email with pytest execution result + :pypi:`pytest-smtpd` + *last release*: May 05, 2023, + *status*: N/A, + *requires*: pytest + + package_description + :pypi:`pytest-snail` *last release*: Nov 04, 2019, *status*: 3 - Alpha, @@ -8572,7 +8604,7 @@ This list contains 1247 plugins. pytest sqlalchemy plugin for mock :pypi:`pytest-sqlalchemy-session` - *last release*: Apr 29, 2023, + *last release*: May 05, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0) @@ -8908,7 +8940,7 @@ This list contains 1247 plugins. Test configuration plugin for pytest. :pypi:`pytest-testdirectory` - *last release*: Feb 21, 2022, + *last release*: May 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -8950,7 +8982,7 @@ This list contains 1247 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Apr 06, 2023, + *last release*: May 02, 2023, *status*: 4 - Beta, *requires*: pytest (<8,>=5) From b1460f32613bc32f4a4e0accac0f6324bc878f8e Mon Sep 17 00:00:00 2001 From: bzoracler <50305397+bzoracler@users.noreply.github.com> Date: Wed, 10 May 2023 10:48:20 +1200 Subject: [PATCH 047/157] fix reference to non-existent module --- 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 143ec190c2d..95b4265ea2f 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -21,7 +21,7 @@ from typing_extensions import Literal from _pytest._code.code import ExceptionRepr - from _pytest.code import ExceptionInfo + from _pytest._code.code import ExceptionInfo from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import PytestPluginManager From aac5d5d08b715ca63fa49a812e5fd97c3da1a062 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 10 May 2023 09:56:10 +0300 Subject: [PATCH 048/157] faulthandler: avoid accessing sys.stderr.encoding Fixes a pytest-xdist regression after 762bb61562d1300eedeb80be2ec2fb8150b3cc3f (not yet released). pytest-xdist patches sys.stderr with an object which doesn't have `encoding`. Strictly speaking, this should be fixed there (or more precisely, in execnet), but it will drop support for older versions which don't want. But in any case, the fix turns out to simplify the code, using FD support added in Python 3.5, so it's good anyway! Refs: https://github.com/pytest-dev/pytest-xdist/pull/900 --- src/_pytest/faulthandler.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index ed29346babd..af879aa44cf 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -2,7 +2,6 @@ import os import sys from typing import Generator -from typing import TextIO import pytest from _pytest.config import Config @@ -11,7 +10,7 @@ from _pytest.stash import StashKey -fault_handler_stderr_key = StashKey[TextIO]() +fault_handler_stderr_fd_key = StashKey[int]() fault_handler_originally_enabled_key = StashKey[bool]() @@ -26,12 +25,9 @@ def pytest_addoption(parser: Parser) -> None: def pytest_configure(config: Config) -> None: import faulthandler - stderr_fd_copy = os.dup(get_stderr_fileno()) - config.stash[fault_handler_stderr_key] = open( - stderr_fd_copy, "w", encoding=sys.stderr.encoding - ) + config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno()) config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled() - faulthandler.enable(file=config.stash[fault_handler_stderr_key]) + faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key]) def pytest_unconfigure(config: Config) -> None: @@ -39,9 +35,9 @@ def pytest_unconfigure(config: Config) -> None: faulthandler.disable() # Close the dup file installed during pytest_configure. - if fault_handler_stderr_key in config.stash: - config.stash[fault_handler_stderr_key].close() - del config.stash[fault_handler_stderr_key] + if fault_handler_stderr_fd_key in config.stash: + os.close(config.stash[fault_handler_stderr_fd_key]) + del config.stash[fault_handler_stderr_fd_key] if config.stash.get(fault_handler_originally_enabled_key, False): # Re-enable the faulthandler if it was originally enabled. faulthandler.enable(file=get_stderr_fileno()) @@ -69,10 +65,10 @@ def get_timeout_config_value(config: Config) -> float: @pytest.hookimpl(hookwrapper=True, trylast=True) def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: timeout = get_timeout_config_value(item.config) - stderr = item.config.stash[fault_handler_stderr_key] - if timeout > 0 and stderr is not None: + if timeout > 0: import faulthandler + stderr = item.config.stash[fault_handler_stderr_fd_key] faulthandler.dump_traceback_later(timeout, file=stderr) try: yield From f84fea08882461a254663f032a9e397279cb6d79 Mon Sep 17 00:00:00 2001 From: leeyueh <69396051+leeyueh@users.noreply.github.com> Date: Wed, 10 May 2023 18:28:52 -0700 Subject: [PATCH 049/157] Update usage.rst (#10974) Added a note for single quotation used in Windows. --- doc/en/how-to/usage.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index c56bef4a6f5..8e2dd86736f 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -35,11 +35,12 @@ Pytest supports several ways to run and select tests from the command-line. .. code-block:: bash - pytest -k "MyClass and not method" + pytest -k 'MyClass and not method' This will run tests which contain names that match the given *string expression* (case-insensitive), which can include Python operators that use filenames, class names and function names as variables. The example above will run ``TestMyClass.test_something`` but not ``TestMyClass.test_method_simple``. +Use ``""`` instead of ``''`` in expression when running this on Windows .. _nodeids: From 78403237cf5026f23618ea7a867bf8b674116e6f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 11 May 2023 15:14:50 -0300 Subject: [PATCH 050/157] Add workflow to close "needs information" labeled issues (#10986) This introduces a workflow to automatically close issues with the label `status: needs information` after a number of days of inactivity. This work has been done manually for a number of years, but I think it is safe to close issues with this label automatically. Not tested yet, but it is in `debug-only` mode so we can watch what it does before deciding to turn it on (however it needs to be in `main` for it to run). --- .github/workflows/stale.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..384d4bc63fd --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: close needs-information issues +on: + schedule: + - cron: "30 1 * * *" + workflow_dispatch: + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/stale@v5 + with: + debug-only: true + days-before-issue-stale: 14 + days-before-issue-close: 7 + only-labels: ["status: needs information"] + stale-issue-label: "stale" + stale-issue-message: "This issue is stale because it has been open for 14 days with no activity." + close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." + days-before-pr-stale: -1 + days-before-pr-close: -1 From b241c0b479bb409e496db5751a97dac0bd3ad4d9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 11 May 2023 09:30:43 -0300 Subject: [PATCH 051/157] Fix defaults for tmp_path_retention_count and tmp_path_retention_policy in docs --- doc/en/reference/reference.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 8b42bf12965..18b2da95376 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1744,7 +1744,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] tmp_path_retention_count = 3 - Default: 3 + Default: ``3`` .. confval:: tmp_path_retention_policy @@ -1763,7 +1763,7 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] tmp_path_retention_policy = "all" - Default: all + Default: ``all`` .. confval:: usefixtures From faeb16146b811488ebbcbd17ef6f9102314065b2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 11 May 2023 09:22:17 -0300 Subject: [PATCH 052/157] Consider testpaths for initial conftests The 'testpaths' option is meant to be identical to execute pytest passing the 'testpaths' directories explicitly. Fix #10987 --- changelog/10987.bugfix.rst | 1 + doc/en/reference/reference.rst | 16 ++++++++++++---- src/_pytest/config/__init__.py | 26 ++++++++++++++++++++++---- testing/test_collection.py | 23 +++++++++++++++++++++++ testing/test_conftest.py | 2 +- 5 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 changelog/10987.bugfix.rst diff --git a/changelog/10987.bugfix.rst b/changelog/10987.bugfix.rst new file mode 100644 index 00000000000..2aafff5f512 --- /dev/null +++ b/changelog/10987.bugfix.rst @@ -0,0 +1 @@ +:confval:`testpaths` is now honored to load root ``conftests``. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 18b2da95376..4bda48386a1 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1713,13 +1713,12 @@ passed multiple times. The expected format is ``name=value``. For example:: .. confval:: testpaths - - Sets list of directories that should be searched for tests when no specific directories, files or test ids are given in the command line when executing pytest from the :ref:`rootdir ` directory. File system paths may use shell-style wildcards, including the recursive ``**`` pattern. + Useful when all project tests are in a known location to speed up test collection and to avoid picking up undesired tests by accident. @@ -1728,8 +1727,17 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] testpaths = testing doc - This tells pytest to only look for tests in ``testing`` and ``doc`` - directories when executing from the root directory. + This configuration means that executing: + + .. code-block:: console + + pytest + + has the same practical effects as executing: + + .. code-block:: console + + pytest testing doc .. confval:: tmp_path_retention_count diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 720f3953153..25cf75e9806 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -526,7 +526,10 @@ def pytest_configure(self, config: "Config") -> None: # Internal API for local conftest plugin handling. # def _set_initial_conftests( - self, namespace: argparse.Namespace, rootpath: Path + self, + namespace: argparse.Namespace, + rootpath: Path, + testpaths_ini: Sequence[str], ) -> None: """Load initial conftest files given a preparsed "namespace". @@ -543,7 +546,7 @@ def _set_initial_conftests( ) self._noconftest = namespace.noconftest self._using_pyargs = namespace.pyargs - testpaths = namespace.file_or_dir + testpaths = namespace.file_or_dir + testpaths_ini foundanchor = False for testpath in testpaths: path = str(testpath) @@ -552,7 +555,20 @@ def _set_initial_conftests( if i != -1: path = path[:i] anchor = absolutepath(current / path) - if anchor.exists(): # we found some file object + + # On Python 3.7 on Windows, anchor.exists() might raise + # if the anchor contains glob characters (for example "*//tests"), specially + # in the case of the 'testpaths' ini option. + # Using an explicit version check to remove this code later once + # Python 3.7 is dropped. + if sys.version_info[:2] == (3, 7): + try: + anchor_exists = anchor.exists() + except OSError: # pragma: no cover + anchor_exists = False + else: + anchor_exists = anchor.exists() + if anchor_exists: # We found some file object. self._try_load_conftest(anchor, namespace.importmode, rootpath) foundanchor = True if not foundanchor: @@ -1131,7 +1147,9 @@ def _processopt(self, opt: "Argument") -> None: @hookimpl(trylast=True) def pytest_load_initial_conftests(self, early_config: "Config") -> None: self.pluginmanager._set_initial_conftests( - early_config.known_args_namespace, rootpath=early_config.rootpath + early_config.known_args_namespace, + rootpath=early_config.rootpath, + testpaths_ini=self.getini("testpaths"), ) def _initini(self, args: Sequence[str]) -> None: diff --git a/testing/test_collection.py b/testing/test_collection.py index d907244d551..f78ae7beafb 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1247,6 +1247,29 @@ def test_collect_pyargs_with_testpaths( result.stdout.fnmatch_lines(["*1 passed in*"]) +def test_initial_conftests_with_testpaths(pytester: Pytester) -> None: + """The testpaths ini option should load conftests in those paths as 'initial' (#10987).""" + p = pytester.mkdir("some_path") + p.joinpath("conftest.py").write_text( + textwrap.dedent( + """ + def pytest_sessionstart(session): + raise Exception("pytest_sessionstart hook is successfully run") + """ + ) + ) + pytester.makeini( + """ + [pytest] + testpaths = some_path + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + "INTERNALERROR* Exception: pytest_sessionstart hook is successfully run" + ) + + def test_collect_symlink_file_arg(pytester: Pytester) -> None: """Collect a direct symlink works even if it does not match python_files (#4325).""" real = pytester.makepyfile( diff --git a/testing/test_conftest.py b/testing/test_conftest.py index d2bf860c6fe..d6abca5368f 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -35,7 +35,7 @@ def __init__(self) -> None: self.importmode = "prepend" namespace = cast(argparse.Namespace, Namespace()) - conftest._set_initial_conftests(namespace, rootpath=Path(args[0])) + conftest._set_initial_conftests(namespace, rootpath=Path(args[0]), testpaths_ini=[]) @pytest.mark.usefixtures("_sys_snapshot") From 2d57d5c32f6cce9058c24317dfce4c3de22ad2a3 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 12 May 2023 09:27:24 -0300 Subject: [PATCH 053/157] Do not break on very long command-line options `_set_initial_conftests` could break on some systems if a very long option was passed, because the `Path.exists()` call raises an `OSError` instead of returning `False`. Fix #10169 --- changelog/10169.bugfix.rst | 1 + src/_pytest/config/__init__.py | 18 ++++++------------ testing/test_collection.py | 23 +++++++++++++++++++++-- 3 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 changelog/10169.bugfix.rst diff --git a/changelog/10169.bugfix.rst b/changelog/10169.bugfix.rst new file mode 100644 index 00000000000..cbf3516a93d --- /dev/null +++ b/changelog/10169.bugfix.rst @@ -0,0 +1 @@ +Fix bug where very long option names could cause pytest to break with ``OSError: [Errno 36] File name too long`` on some systems. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 25cf75e9806..74905ff4c8e 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -556,19 +556,13 @@ def _set_initial_conftests( path = path[:i] anchor = absolutepath(current / path) - # On Python 3.7 on Windows, anchor.exists() might raise - # if the anchor contains glob characters (for example "*//tests"), specially - # in the case of the 'testpaths' ini option. - # Using an explicit version check to remove this code later once - # Python 3.7 is dropped. - if sys.version_info[:2] == (3, 7): - try: - anchor_exists = anchor.exists() - except OSError: # pragma: no cover - anchor_exists = False - else: + # Ensure we do not break if what appears to be an anchor + # is in fact a very long option (#10169). + try: anchor_exists = anchor.exists() - if anchor_exists: # We found some file object. + except OSError: # pragma: no cover + anchor_exists = False + if anchor_exists: self._try_load_conftest(anchor, namespace.importmode, rootpath) foundanchor = True if not foundanchor: diff --git a/testing/test_collection.py b/testing/test_collection.py index f78ae7beafb..bbcb358b6ff 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1254,7 +1254,7 @@ def test_initial_conftests_with_testpaths(pytester: Pytester) -> None: textwrap.dedent( """ def pytest_sessionstart(session): - raise Exception("pytest_sessionstart hook is successfully run") + raise Exception("pytest_sessionstart hook successfully run") """ ) ) @@ -1266,10 +1266,29 @@ def pytest_sessionstart(session): ) result = pytester.runpytest() result.stdout.fnmatch_lines( - "INTERNALERROR* Exception: pytest_sessionstart hook is successfully run" + "INTERNALERROR* Exception: pytest_sessionstart hook successfully run" ) +def test_large_option_breaks_initial_conftests(pytester: Pytester) -> None: + """Long option values do not break initial conftests handling (#10169).""" + option_value = "x" * 1024 * 1000 + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addoption("--xx", default=None) + """ + ) + pytester.makepyfile( + f""" + def test_foo(request): + assert request.config.getoption("xx") == {option_value!r} + """ + ) + result = pytester.runpytest(f"--xx={option_value}") + assert result.ret == 0 + + def test_collect_symlink_file_arg(pytester: Pytester) -> None: """Collect a direct symlink works even if it does not match python_files (#4325).""" real = pytester.makepyfile( From 4cc05e7bee158ba12698880e8bb83d5040aa277d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 12 May 2023 09:34:44 -0300 Subject: [PATCH 054/157] Fix trailing whitespace in .github/workflows/stale.yml --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 384d4bc63fd..eba0eefd72e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,7 @@ name: close needs-information issues on: schedule: - cron: "30 1 * * *" - workflow_dispatch: + workflow_dispatch: jobs: close-issues: From d9d78a8aef9619a9efc5a4c835a00af06ee1e863 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 13 May 2023 22:24:30 +0300 Subject: [PATCH 055/157] pre-commit: remove `default_language_version` setting This makes it difficult to run on newer python versions than the one specified. --- .pre-commit-config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce621360ed5..5b9f31ced46 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,3 @@ -default_language_version: - python: "3.10" repos: - repo: https://github.com/psf/black rev: 23.3.0 From 23e343af6018ef3dcf8650e9b3c4a8da0fabe566 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 14 May 2023 08:39:45 -0300 Subject: [PATCH 056/157] Fix close stale issues workflow (#10990) Fixed how the label is configured. --- .github/workflows/stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index eba0eefd72e..a1120c3e200 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/stale@v5 with: - debug-only: true + debug-only: false days-before-issue-stale: 14 days-before-issue-close: 7 - only-labels: ["status: needs information"] + only-labels: "status: needs information" stale-issue-label: "stale" stale-issue-message: "This issue is stale because it has been open for 14 days with no activity." close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." From 3b5b3cf50ee514773c14626419b472625e76e438 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Sun, 14 May 2023 14:17:00 -0500 Subject: [PATCH 057/157] monkeypatch: add support for TypedDict (#11000) --- AUTHORS | 1 + changelog/10999.bugfix.rst | 1 + src/_pytest/monkeypatch.py | 19 ++++++++++++------- testing/typing_checks.py | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 changelog/10999.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 438be759814..a6112565e34 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,7 @@ Abdeali JK Abdelrahman Elbehery Abhijeet Kasurde Adam Johnson +Adam Stewart Adam Uhlir Ahn Ki-Wook Akiomi Kamakura diff --git a/changelog/10999.bugfix.rst b/changelog/10999.bugfix.rst new file mode 100644 index 00000000000..08c68da01bf --- /dev/null +++ b/changelog/10999.bugfix.rst @@ -0,0 +1 @@ +The `monkeypatch` `setitem`/`delitem` type annotations now allow `TypedDict` arguments. diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index c6e29ac7642..9e51ff33538 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -7,6 +7,7 @@ from typing import Any from typing import Generator from typing import List +from typing import Mapping from typing import MutableMapping from typing import Optional from typing import overload @@ -129,7 +130,7 @@ class MonkeyPatch: def __init__(self) -> None: self._setattr: List[Tuple[object, str, object]] = [] - self._setitem: List[Tuple[MutableMapping[Any, Any], object, object]] = [] + self._setitem: List[Tuple[Mapping[Any, Any], object, object]] = [] self._cwd: Optional[str] = None self._savesyspath: Optional[List[str]] = None @@ -290,12 +291,13 @@ def delattr( self._setattr.append((target, name, oldval)) delattr(target, name) - def setitem(self, dic: MutableMapping[K, V], name: K, value: V) -> None: + def setitem(self, dic: Mapping[K, V], name: K, value: V) -> None: """Set dictionary entry ``name`` to value.""" self._setitem.append((dic, name, dic.get(name, notset))) - dic[name] = value + # Not all Mapping types support indexing, but MutableMapping doesn't support TypedDict + dic[name] = value # type: ignore[index] - def delitem(self, dic: MutableMapping[K, V], name: K, raising: bool = True) -> None: + def delitem(self, dic: Mapping[K, V], name: K, raising: bool = True) -> None: """Delete ``name`` from dict. Raises ``KeyError`` if it doesn't exist, unless ``raising`` is set to @@ -306,7 +308,8 @@ def delitem(self, dic: MutableMapping[K, V], name: K, raising: bool = True) -> N raise KeyError(name) else: self._setitem.append((dic, name, dic.get(name, notset))) - del dic[name] + # Not all Mapping types support indexing, but MutableMapping doesn't support TypedDict + del dic[name] # type: ignore[attr-defined] def setenv(self, name: str, value: str, prepend: Optional[str] = None) -> None: """Set environment variable ``name`` to ``value``. @@ -401,11 +404,13 @@ def undo(self) -> None: for dictionary, key, value in reversed(self._setitem): if value is notset: try: - del dictionary[key] + # Not all Mapping types support indexing, but MutableMapping doesn't support TypedDict + del dictionary[key] # type: ignore[attr-defined] except KeyError: pass # Was already deleted, so we have the desired state. else: - dictionary[key] = value + # Not all Mapping types support indexing, but MutableMapping doesn't support TypedDict + dictionary[key] = value # type: ignore[index] self._setitem[:] = [] if self._savesyspath is not None: sys.path[:] = self._savesyspath diff --git a/testing/typing_checks.py b/testing/typing_checks.py index d15b3988bb5..57f2bae475f 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -9,6 +9,7 @@ from typing_extensions import assert_type import pytest +from pytest import MonkeyPatch # Issue #7488. @@ -29,6 +30,19 @@ def check_parametrize_ids_callable(func) -> None: pass +# Issue #10999. +def check_monkeypatch_typeddict(monkeypatch: MonkeyPatch) -> None: + from typing import TypedDict + + class Foo(TypedDict): + x: int + y: float + + a: Foo = {"x": 1, "y": 3.14} + monkeypatch.setitem(a, "x", 2) + monkeypatch.delitem(a, "y") + + def check_raises_is_a_context_manager(val: bool) -> None: with pytest.raises(RuntimeError) if val else contextlib.nullcontext() as excinfo: pass From 383774db1057830fb303c39de6d9ab7741492d87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 07:29:18 +0200 Subject: [PATCH 058/157] build(deps): Bump actions/stale from 5 to 8 (#11003) Bumps [actions/stale](https://github.com/actions/stale) from 5 to 8. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v5...v8) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index a1120c3e200..3f8ca186f0e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: permissions: issues: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v8 with: debug-only: false days-before-issue-stale: 14 From 612489e2bdf0c39818474e7c4e37b367646f79ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 08:26:41 -0300 Subject: [PATCH 059/157] [automated] Update plugin list (#11001) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 98 +++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 66b7beb138b..2cb886ed4d1 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1251 plugins. +This list contains 1255 plugins. .. only:: not latex @@ -50,7 +50,7 @@ This list contains 1251 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 05, 2023 5 - Production/Stable pytest (<8.0.0,>=6) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 11, 2023 5 - Production/Stable pytest (<8.0.0,>=6) :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -141,7 +141,7 @@ This list contains 1251 plugins. :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A - :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. Feb 14, 2023 3 - Alpha pytest + :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jan 29, 2023 5 - Production/Stable pytest (>=6.2.0) :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A @@ -376,7 +376,7 @@ This list contains 1251 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins Jan 27, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-enabler` Enable installed pytest plugins May 12, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A @@ -486,7 +486,7 @@ This list contains 1251 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 15, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 11, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -535,7 +535,8 @@ This list contains 1251 plugins. :pypi:`pytest-html-report-merger` Aug 31, 2022 N/A N/A :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A - :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Mar 16, 2022 5 - Production/Stable pytest ; extra == 'test' + :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest Sep 12, 2022 3 - Alpha N/A @@ -571,7 +572,7 @@ This list contains 1251 plugins. :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0) :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) - :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 01, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 09, 2023 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 13, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A @@ -648,7 +649,7 @@ This list contains 1251 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment May 05, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment May 08, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -830,7 +831,7 @@ This list contains 1251 plugins. :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A - :pypi:`pytest-pop` A pytest plugin to help with testing pop projects Mar 16, 2023 5 - Production/Stable pytest + :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 11, 2022 5 - Production/Stable pytest (>=6.2.0) @@ -861,20 +862,22 @@ This list contains 1251 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jan 05, 2023 N/A pytest + :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" May 10, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 08, 2023 N/A pytest (>=7.3.1) :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Nov 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvista` Pytest-pyvista package Mar 19, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 02, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 26, 2022 5 - Production/Stable pytest (>=6.2.3) @@ -986,14 +989,14 @@ This list contains 1251 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 03, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 03, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1073,6 +1076,7 @@ This list contains 1251 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-static` pytest-static May 07, 2023 1 - Planning N/A :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1119,7 +1123,7 @@ This list contains 1251 plugins. :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures Dec 01, 2022 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods May 02, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods May 12, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5) @@ -1224,7 +1228,7 @@ This list contains 1251 plugins. :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` Feb 27, 2023 N/A pytest + :pypi:`pytest-wake` May 11, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Continiously runs pytest on changes in \*.py files Dec 11, 2022 3 - Alpha N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A @@ -1238,7 +1242,7 @@ This list contains 1251 plugins. :pypi:`pytest-wiremock` A pytest plugin for programmatically using wiremock in integration tests Mar 27, 2022 N/A pytest (>=7.1.1,<8.0.0) :pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Jan 13, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Mar 12, 2023 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs May 12, 2023 5 - Production/Stable pytest (>=6.2.0) :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) @@ -1257,7 +1261,7 @@ This list contains 1251 plugins. :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml Mar 21, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 08, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A @@ -1499,7 +1503,7 @@ This list contains 1251 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: May 05, 2023, + *last release*: May 11, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0.0,>=6) @@ -2136,7 +2140,7 @@ This list contains 1251 plugins. \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. :pypi:`pytest-budosystems` - *last release*: Feb 14, 2023, + *last release*: May 07, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -3781,7 +3785,7 @@ This list contains 1251 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Jan 27, 2023, + *last release*: May 12, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -4551,7 +4555,7 @@ This list contains 1251 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Mar 15, 2023, + *last release*: May 11, 2023, *status*: N/A, *requires*: N/A @@ -4894,12 +4898,19 @@ This list contains 1251 plugins. Fixture "http" for http requests :pypi:`pytest-httpbin` - *last release*: Mar 16, 2022, + *last release*: May 08, 2023, *status*: 5 - Production/Stable, *requires*: pytest ; extra == 'test' Easily test your HTTP library against a local copy of httpbin + :pypi:`pytest-httpdbg` + *last release*: May 09, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0) + + A pytest plugin to record HTTP(S) requests with stack trace + :pypi:`pytest-http-mocker` *last release*: Oct 20, 2019, *status*: N/A, @@ -5146,7 +5157,7 @@ This list contains 1251 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: May 01, 2023, + *last release*: May 09, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5685,7 +5696,7 @@ This list contains 1251 plugins. :pypi:`pytest-logikal` - *last release*: May 05, 2023, + *last release*: May 08, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -6959,7 +6970,7 @@ This list contains 1251 plugins. Visualize your failed tests with poo :pypi:`pytest-pop` - *last release*: Mar 16, 2023, + *last release*: May 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7176,7 +7187,7 @@ This list contains 1251 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jan 05, 2023, + *last release*: May 10, 2023, *status*: N/A, *requires*: pytest @@ -7224,6 +7235,13 @@ This list contains 1251 plugins. Pyramid server fixture for py.test + :pypi:`pytest-pyreport` + *last release*: May 08, 2023, + *status*: N/A, + *requires*: pytest (>=7.3.1) + + PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report + :pypi:`pytest-pyright` *last release*: Nov 20, 2022, *status*: 4 - Beta, @@ -7238,6 +7256,13 @@ This list contains 1251 plugins. A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". + :pypi:`pytest-pystack` + *last release*: May 07, 2023, + *status*: N/A, + *requires*: pytest (>=3.5.0) + + Plugin to run pystack after a timeout for a test suite. + :pypi:`pytest-pytestrail` *last release*: Aug 27, 2020, *status*: 4 - Beta, @@ -7267,7 +7292,7 @@ This list contains 1251 plugins. Pytest-pyvista package :pypi:`pytest-qaseio` - *last release*: May 02, 2023, + *last release*: May 11, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.2.2,<8.0.0) @@ -8051,7 +8076,7 @@ This list contains 1251 plugins. :pypi:`pytest-sbase` - *last release*: May 03, 2023, + *last release*: May 12, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8100,7 +8125,7 @@ This list contains 1251 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: May 03, 2023, + *last release*: May 12, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8659,6 +8684,13 @@ This list contains 1251 plugins. A package to prevent Dependency Confusion attacks against Yandex. + :pypi:`pytest-static` + *last release*: May 07, 2023, + *status*: 1 - Planning, + *requires*: N/A + + pytest-static + :pypi:`pytest-statsd` *last release*: Nov 30, 2018, *status*: 5 - Production/Stable, @@ -8982,7 +9014,7 @@ This list contains 1251 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: May 02, 2023, + *last release*: May 12, 2023, *status*: 4 - Beta, *requires*: pytest (<8,>=5) @@ -9717,7 +9749,7 @@ This list contains 1251 plugins. Pytest plugin for testing whatsapp bots with end to end tests :pypi:`pytest-wake` - *last release*: Feb 27, 2023, + *last release*: May 11, 2023, *status*: N/A, *requires*: pytest @@ -9815,7 +9847,7 @@ This list contains 1251 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: Mar 12, 2023, + *last release*: May 12, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2.0) @@ -9948,7 +9980,7 @@ This list contains 1251 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: Mar 21, 2023, + *last release*: May 08, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) From b8edacb8f1e79d6f5b37e46868d6b1b50c13ad3f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 09:19:38 +0200 Subject: [PATCH 060/157] [pre-commit.ci] pre-commit autoupdate (#11007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.2.0 → v1.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.2.0...v1.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5b9f31ced46..af6cd262300 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.2.0 + rev: v1.3.0 hooks: - id: mypy files: ^(src/|testing/) From 163632299565ec33b8566dc39f6b46c15b922953 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 16 May 2023 20:24:06 -0300 Subject: [PATCH 061/157] Reference "Status of Python Versions" in backwards-compatibility policy As suggested in #10981. --- doc/en/backwards-compatibility.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index 64bcbf5bd49..ea0c6a71a28 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -92,3 +92,5 @@ pytest version min. Python version 5.0 - 6.1 3.5+ 3.3 - 4.6 2.7, 3.4+ ============== =================== + +`Status of Python Versions `__. From 6041511fb4f43e5c1139ccdca169e0c849d00d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 18 May 2023 16:10:44 +0300 Subject: [PATCH 062/157] Spelling and grammar fixes (#11014) --- doc/en/changelog.rst | 4 ++-- doc/en/conf.py | 2 +- doc/en/reference/reference.rst | 4 ++-- src/_pytest/capture.py | 2 +- src/_pytest/tmpdir.py | 2 +- src/_pytest/warning_types.py | 2 +- testing/test_python_path.py | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index c13c05936d5..7d6eb1ffacc 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -567,7 +567,7 @@ Breaking Changes - `#7259 `_: The :ref:`Node.reportinfo() ` function first return value type has been expanded from `py.path.local | str` to `os.PathLike[str] | str`. Most plugins which refer to `reportinfo()` only define it as part of a custom :class:`pytest.Item` implementation. - Since `py.path.local` is a `os.PathLike[str]`, these plugins are unaffacted. + Since `py.path.local` is an `os.PathLike[str]`, these plugins are unaffacted. Plugins and users which call `reportinfo()`, use the first return value and interact with it as a `py.path.local`, would need to adjust by calling `py.path.local(fspath)`. Although preferably, avoid the legacy `py.path.local` and use `pathlib.Path`, or use `item.location` or `item.path`, instead. @@ -4067,7 +4067,7 @@ Removals See our :ref:`docs ` on information on how to update your code. -- :issue:`4546`: Remove ``Node.get_marker(name)`` the return value was not usable for more than a existence check. +- :issue:`4546`: Remove ``Node.get_marker(name)`` the return value was not usable for more than an existence check. Use ``Node.get_closest_marker(name)`` as a replacement. diff --git a/doc/en/conf.py b/doc/en/conf.py index 5184ee7b1e5..32f508219a6 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -341,7 +341,7 @@ # The scheme of the identifier. Typical schemes are ISBN or URL. # epub_scheme = '' -# The unique identifier of the text. This can be a ISBN number +# The unique identifier of the text. This can be an ISBN number # or the project homepage. # epub_identifier = '' diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 4bda48386a1..48fbe2734de 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1049,11 +1049,11 @@ Environment variables that can be used to change pytest's behavior. .. envvar:: CI -When set (regardless of value), pytest acknowledges that is running in a CI process. Alterative to ``BUILD_NUMBER`` variable. +When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to ``BUILD_NUMBER`` variable. .. envvar:: BUILD_NUMBER -When set (regardless of value), pytest acknowledges that is running in a CI process. Alterative to CI variable. +When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to CI variable. .. envvar:: PYTEST_ADDOPTS diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 275322cc335..a8ca0869f33 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -241,7 +241,7 @@ def tell(self) -> int: raise UnsupportedOperation("redirected stdin is pseudofile, has no tell()") def truncate(self, size: Optional[int] = None) -> int: - raise UnsupportedOperation("cannont truncate stdin") + raise UnsupportedOperation("cannot truncate stdin") def write(self, data: str) -> int: raise UnsupportedOperation("cannot write to stdin") diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index d7f5ab9b459..3cc2bace55b 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -100,7 +100,7 @@ def from_config( policy = config.getini("tmp_path_retention_policy") if policy not in ("all", "failed", "none"): raise ValueError( - f"tmp_path_retention_policy must be either all, failed, none. Current intput: {policy}." + f"tmp_path_retention_policy must be either all, failed, none. Current input: {policy}." ) return cls( diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 86fa9a07e0c..bd5f4187343 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -149,7 +149,7 @@ def warn_explicit_for(method: FunctionType, message: PytestWarning) -> None: """ Issue the warning :param:`message` for the definition of the given :param:`method` - this helps to log warnigns for functions defined prior to finding an issue with them + this helps to log warnings for functions defined prior to finding an issue with them (like hook wrappers being marked in a legacy mechanism) """ lineno = method.__code__.co_firstlineno diff --git a/testing/test_python_path.py b/testing/test_python_path.py index 5ee0f55e36a..e1628feb159 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -82,7 +82,7 @@ def test_no_ini(pytester: Pytester, file_structure) -> None: def test_clean_up(pytester: Pytester) -> None: """Test that the plugin cleans up after itself.""" - # This is tough to test behaviorly because the cleanup really runs last. + # This is tough to test behaviorally because the cleanup really runs last. # So the test make several implementation assumptions: # - Cleanup is done in pytest_unconfigure(). # - Not a hookwrapper. From c8641f879f3dac0ce92338a6b87b687b7efe25d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 18 May 2023 16:11:47 +0300 Subject: [PATCH 063/157] Include reason in cache path warnings to aid debugging (#11005) Co-authored-by: Bruno Oliveira --- changelog/11005.improvement.rst | 1 + src/_pytest/cacheprovider.py | 14 ++++++++++---- testing/test_cacheprovider.py | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 changelog/11005.improvement.rst diff --git a/changelog/11005.improvement.rst b/changelog/11005.improvement.rst new file mode 100644 index 00000000000..295252514a6 --- /dev/null +++ b/changelog/11005.improvement.rst @@ -0,0 +1 @@ +Added underlying exception to cache provider path creation and write warning messages. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 719b32f7e0e..89a4a55f8fc 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -179,16 +179,22 @@ def set(self, key: str, value: object) -> None: else: cache_dir_exists_already = self._cachedir.exists() path.parent.mkdir(exist_ok=True, parents=True) - except OSError: - self.warn("could not create cache path {path}", path=path, _ispytest=True) + except OSError as exc: + self.warn( + f"could not create cache path {path}: {exc}", + _ispytest=True, + ) return if not cache_dir_exists_already: self._ensure_supporting_files() data = json.dumps(value, ensure_ascii=False, indent=2) try: f = path.open("w", encoding="UTF-8") - except OSError: - self.warn("cache could not write path {path}", path=path, _ispytest=True) + except OSError as exc: + self.warn( + f"cache could not write path {path}: {exc}", + _ispytest=True, + ) else: with f: f.write(data) diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 2f8517f9962..ee2fe1845df 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -87,7 +87,7 @@ def test_cache_failure_warns( "*= warnings summary =*", "*/cacheprovider.py:*", " */cacheprovider.py:*: PytestCacheWarning: could not create cache path " - f"{unwritable_cache_dir}/v/cache/nodeids", + f"{unwritable_cache_dir}/v/cache/nodeids: *", ' config.cache.set("cache/nodeids", sorted(self.cached_nodeids))', "*1 failed, 3 warnings in*", ] From ba32a3bd87e92d87d777a62414972374cbbfddf2 Mon Sep 17 00:00:00 2001 From: Alex Lambson Date: Thu, 18 May 2023 07:18:59 -0600 Subject: [PATCH 064/157] Handle disabled logging in 'caplog.set_level' and 'caplog.at_level' (#8758) Forces requested `caplog` logging levels to be enabled if they were disabled via `logging.disable()` `[attr-defined]` mypy error ignored in `logging.py` because there were existing errors with the imports and `loggin.Logger.manager` is an attr set at runtime. Since it's in the standard lib I can't really fix that. Ignored an attr-defined error in `src/_pytest/config/__init__.py` because the re-export is necessary. Fixes #8711 --- AUTHORS | 1 + changelog/8711.improvement.rst | 3 + src/_pytest/config/__init__.py | 2 +- src/_pytest/logging.py | 50 ++++++++++++- testing/logging/test_fixture.py | 123 +++++++++++++++++++++++++++++++- 5 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 changelog/8711.improvement.rst diff --git a/AUTHORS b/AUTHORS index a6112565e34..92b0b2a1a55 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,6 +15,7 @@ Akiomi Kamakura Alan Velasco Alessio Izzo Alex Jones +Alex Lambson Alexander Johnson Alexander King Alexei Kozlenok diff --git a/changelog/8711.improvement.rst b/changelog/8711.improvement.rst new file mode 100644 index 00000000000..20805e9f94d --- /dev/null +++ b/changelog/8711.improvement.rst @@ -0,0 +1,3 @@ +:func:`_pytest.logging.LogCaptureFixture.set_level` and :func:`_pytest.logging.LogCaptureFixture.at_level` +will temporarily enable the requested ``level`` if ``level`` was disabled globally via +``logging.disable(LEVEL)``. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 74905ff4c8e..6df06f7b281 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -49,7 +49,7 @@ from _pytest._code import filter_traceback from _pytest._io import TerminalWriter from _pytest.compat import final -from _pytest.compat import importlib_metadata +from _pytest.compat import importlib_metadata # type: ignore[attr-defined] from _pytest.outcomes import fail from _pytest.outcomes import Skipped from _pytest.pathlib import absolutepath diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 2480a5edd29..95774dd1472 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -376,11 +376,12 @@ def __init__(self, item: nodes.Node, *, _ispytest: bool = False) -> None: self._initial_handler_level: Optional[int] = None # Dict of log name -> log level. self._initial_logger_levels: Dict[Optional[str], int] = {} + self._initial_disabled_logging_level: Optional[int] = None def _finalize(self) -> None: """Finalize the fixture. - This restores the log levels changed by :meth:`set_level`. + This restores the log levels and the disabled logging levels changed by :meth:`set_level`. """ # Restore log levels. if self._initial_handler_level is not None: @@ -388,6 +389,10 @@ def _finalize(self) -> None: for logger_name, level in self._initial_logger_levels.items(): logger = logging.getLogger(logger_name) logger.setLevel(level) + # Disable logging at the original disabled logging level. + if self._initial_disabled_logging_level is not None: + logging.disable(self._initial_disabled_logging_level) + self._initial_disabled_logging_level = None @property def handler(self) -> LogCaptureHandler: @@ -453,6 +458,40 @@ def clear(self) -> None: """Reset the list of log records and the captured log text.""" self.handler.clear() + def _force_enable_logging( + self, level: Union[int, str], logger_obj: logging.Logger + ) -> int: + """Enable the desired logging level if the global level was disabled via ``logging.disabled``. + + Only enables logging levels greater than or equal to the requested ``level``. + + Does nothing if the desired ``level`` wasn't disabled. + + :param level: + The logger level caplog should capture. + All logging is enabled if a non-standard logging level string is supplied. + Valid level strings are in :data:`logging._nameToLevel`. + :param logger_obj: The logger object to check. + + :return: The original disabled logging level. + """ + original_disable_level: int = logger_obj.manager.disable # type: ignore[attr-defined] + + if isinstance(level, str): + # Try to translate the level string to an int for `logging.disable()` + level = logging.getLevelName(level) + + if not isinstance(level, int): + # The level provided was not valid, so just un-disable all logging. + logging.disable(logging.NOTSET) + elif not logger_obj.isEnabledFor(level): + # Each level is `10` away from other levels. + # https://docs.python.org/3/library/logging.html#logging-levels + disable_level = max(level - 10, logging.NOTSET) + logging.disable(disable_level) + + return original_disable_level + def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: """Set the level of a logger for the duration of a test. @@ -460,6 +499,8 @@ def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> Non The levels of the loggers changed by this function will be restored to their initial values at the end of the test. + Will enable the requested logging level if it was disabled via :meth:`logging.disable`. + :param level: The level. :param logger: The logger to update. If not given, the root logger. """ @@ -470,6 +511,9 @@ def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> Non if self._initial_handler_level is None: self._initial_handler_level = self.handler.level self.handler.setLevel(level) + initial_disabled_logging_level = self._force_enable_logging(level, logger_obj) + if self._initial_disabled_logging_level is None: + self._initial_disabled_logging_level = initial_disabled_logging_level @contextmanager def at_level( @@ -479,6 +523,8 @@ def at_level( the end of the 'with' statement the level is restored to its original value. + Will enable the requested logging level if it was disabled via :meth:`logging.disable`. + :param level: The level. :param logger: The logger to update. If not given, the root logger. """ @@ -487,11 +533,13 @@ def at_level( logger_obj.setLevel(level) handler_orig_level = self.handler.level self.handler.setLevel(level) + original_disable_level = self._force_enable_logging(level, logger_obj) try: yield finally: logger_obj.setLevel(orig_level) self.handler.setLevel(handler_orig_level) + logging.disable(original_disable_level) @fixture diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index e9e73d05f98..8eaa2de96a8 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -1,3 +1,4 @@ +# mypy: disable-error-code="attr-defined" import logging import pytest @@ -8,6 +9,19 @@ sublogger = logging.getLogger(__name__ + ".baz") +@pytest.fixture +def cleanup_disabled_logging(): + """Simple fixture that ensures that a test doesn't disable logging. + + This is necessary because ``logging.disable()`` is global, so a test disabling logging + and not cleaning up after will break every test that runs after it. + + This behavior was moved to a fixture so that logging will be un-disabled even if the test fails an assertion. + """ + yield + logging.disable(logging.NOTSET) + + def test_fixture_help(pytester: Pytester) -> None: result = pytester.runpytest("--fixtures") result.stdout.fnmatch_lines(["*caplog*"]) @@ -28,10 +42,27 @@ def test_change_level(caplog): assert "CRITICAL" in caplog.text +def test_change_level_logging_disabled(caplog, cleanup_disabled_logging): + logging.disable(logging.CRITICAL) + assert logging.root.manager.disable == logging.CRITICAL + caplog.set_level(logging.WARNING) + logger.info("handler INFO level") + logger.warning("handler WARNING level") + + caplog.set_level(logging.CRITICAL, logger=sublogger.name) + sublogger.warning("logger SUB_WARNING level") + sublogger.critical("logger SUB_CRITICAL level") + + assert "INFO" not in caplog.text + assert "WARNING" in caplog.text + assert "SUB_WARNING" not in caplog.text + assert "SUB_CRITICAL" in caplog.text + + def test_change_level_undo(pytester: Pytester) -> None: """Ensure that 'set_level' is undone after the end of the test. - Tests the logging output themselves (affacted both by logger and handler levels). + Tests the logging output themselves (affected both by logger and handler levels). """ pytester.makepyfile( """ @@ -54,6 +85,37 @@ def test2(caplog): result.stdout.no_fnmatch_line("*log from test2*") +def test_change_disabled_level_undo( + pytester: Pytester, cleanup_disabled_logging +) -> None: + """Ensure that '_force_enable_logging' in 'set_level' is undone after the end of the test. + + Tests the logging output themselves (affected by disabled logging level). + """ + pytester.makepyfile( + """ + import logging + + def test1(caplog): + logging.disable(logging.CRITICAL) + caplog.set_level(logging.INFO) + # using + operator here so fnmatch_lines doesn't match the code in the traceback + logging.info('log from ' + 'test1') + assert 0 + + def test2(caplog): + # using + operator here so fnmatch_lines doesn't match the code in the traceback + # use logging.warning because we need a level that will show up if logging.disabled + # isn't reset to ``CRITICAL`` after test1. + logging.warning('log from ' + 'test2') + assert 0 + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines(["*log from test1*", "*2 failed in *"]) + result.stdout.no_fnmatch_line("*log from test2*") + + def test_change_level_undos_handler_level(pytester: Pytester) -> None: """Ensure that 'set_level' is undone after the end of the test (handler). @@ -97,6 +159,65 @@ def test_with_statement(caplog): assert "CRITICAL" in caplog.text +def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): + logging.disable(logging.CRITICAL) + assert logging.root.manager.disable == logging.CRITICAL + with caplog.at_level(logging.WARNING): + logger.debug("handler DEBUG level") + logger.info("handler INFO level") + logger.warning("handler WARNING level") + logger.error("handler ERROR level") + logger.critical("handler CRITICAL level") + + assert logging.root.manager.disable == logging.INFO + + with caplog.at_level(logging.CRITICAL, logger=sublogger.name): + sublogger.warning("logger SUB_WARNING level") + sublogger.critical("logger SUB_CRITICAL level") + + assert "DEBUG" not in caplog.text + assert "INFO" not in caplog.text + assert "WARNING" in caplog.text + assert "ERROR" in caplog.text + assert " CRITICAL" in caplog.text + assert "SUB_WARNING" not in caplog.text + assert "SUB_CRITICAL" in caplog.text + assert logging.root.manager.disable == logging.CRITICAL + + +@pytest.mark.parametrize( + "level_str,expected_disable_level", + [ + ("CRITICAL", logging.ERROR), + ("ERROR", logging.WARNING), + ("WARNING", logging.INFO), + ("INFO", logging.DEBUG), + ("DEBUG", logging.NOTSET), + ("NOTSET", logging.NOTSET), + ("NOTVALIDLEVEL", logging.NOTSET), + ], +) +def test_force_enable_logging_level_string( + caplog, cleanup_disabled_logging, level_str, expected_disable_level +): + """Test _force_enable_logging using a level string. + + ``expected_disable_level`` is one level below ``level_str`` because the disabled log level + always needs to be *at least* one level lower than the level that caplog is trying to capture. + """ + test_logger = logging.getLogger("test_str_level_force_enable") + # Emulate a testing environment where all logging is disabled. + logging.disable(logging.CRITICAL) + # Make sure all logging is disabled. + assert not test_logger.isEnabledFor(logging.CRITICAL) + # Un-disable logging for `level_str`. + caplog._force_enable_logging(level_str, test_logger) + # Make sure that the disabled level is now one below the requested logging level. + # We don't use `isEnabledFor` here because that also checks the level set by + # `logging.setLevel()` which is irrelevant to `logging.disable()`. + assert test_logger.manager.disable == expected_disable_level + + def test_log_access(caplog): caplog.set_level(logging.INFO) logger.info("boo %s", "arg") From 9fa82598a96ce28013630a45ef4af0074f73f944 Mon Sep 17 00:00:00 2001 From: Roberto Aldera <51328612+roberto-aldera@users.noreply.github.com> Date: Fri, 19 May 2023 13:24:28 +0200 Subject: [PATCH 065/157] Use NamedTuple for pytest_report_teststatus return value (#10972) Closes #10872 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/10872.improvement.rst | 1 + doc/en/reference/reference.rst | 6 ++++++ src/_pytest/hookspec.py | 3 ++- src/_pytest/terminal.py | 30 ++++++++++++++++++++++++++---- src/pytest/__init__.py | 2 ++ 6 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 changelog/10872.improvement.rst diff --git a/AUTHORS b/AUTHORS index 92b0b2a1a55..c9e990bf1bb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -308,6 +308,7 @@ Rafal Semik Raquel Alegre Ravi Chandra Robert Holt +Roberto Aldera Roberto Polli Roland Puntaier Romain Dorgueil diff --git a/changelog/10872.improvement.rst b/changelog/10872.improvement.rst new file mode 100644 index 00000000000..fe0c01a0224 --- /dev/null +++ b/changelog/10872.improvement.rst @@ -0,0 +1 @@ +Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 48fbe2734de..6a5512cc11d 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -956,6 +956,12 @@ TestReport :show-inheritance: :inherited-members: +TestShortLogReport +~~~~~~~~~~~~~~~~~~ + +.. autoclass:: pytest.TestShortLogReport() + :members: + _Result ~~~~~~~ diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 95b4265ea2f..1f7c368f792 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -41,6 +41,7 @@ from _pytest.reports import TestReport from _pytest.runner import CallInfo from _pytest.terminal import TerminalReporter + from _pytest.terminal import TestShortLogReport from _pytest.compat import LEGACY_PATH @@ -806,7 +807,7 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] @hookspec(firstresult=True) def pytest_report_teststatus( # type:ignore[empty-body] report: Union["CollectReport", "TestReport"], config: "Config" -) -> Tuple[str, str, Union[str, Mapping[str, bool]]]: +) -> "TestShortLogReport | Tuple[str, str, Union[str, Tuple[str, Mapping[str, bool]]]]": """Return result-category, shortletter and verbose word for status reporting. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index b7793d398ce..b0cdb58ce00 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -21,6 +21,7 @@ from typing import Generator from typing import List from typing import Mapping +from typing import NamedTuple from typing import Optional from typing import Sequence from typing import Set @@ -112,6 +113,26 @@ def __call__( namespace.quiet = getattr(namespace, "quiet", 0) + 1 +class TestShortLogReport(NamedTuple): + """Used to store the test status result category, shortletter and verbose word. + For example ``"rerun", "R", ("RERUN", {"yellow": True})``. + + :ivar category: + The class of result, for example ``“passed”``, ``“skipped”``, ``“error”``, or the empty string. + + :ivar letter: + The short letter shown as testing progresses, for example ``"."``, ``"s"``, ``"E"``, or the empty string. + + :ivar word: + Verbose word is shown as testing progresses in verbose mode, for example ``"PASSED"``, ``"SKIPPED"``, + ``"ERROR"``, or the empty string. + """ + + category: str + letter: str + word: Union[str, Tuple[str, Mapping[str, bool]]] + + def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("terminal reporting", "Reporting", after="general") group._addoption( @@ -548,10 +569,11 @@ def pytest_runtest_logstart( def pytest_runtest_logreport(self, report: TestReport) -> None: self._tests_ran = True rep = report - res: Tuple[ - str, str, Union[str, Tuple[str, Mapping[str, bool]]] - ] = self.config.hook.pytest_report_teststatus(report=rep, config=self.config) - category, letter, word = res + + res = TestShortLogReport( + *self.config.hook.pytest_report_teststatus(report=rep, config=self.config) + ) + category, letter, word = res.category, res.letter, res.word if not isinstance(word, tuple): markup = None else: diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index f25ecde9c47..9c1d5d204d8 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -62,6 +62,7 @@ from _pytest.runner import CallInfo from _pytest.stash import Stash from _pytest.stash import StashKey +from _pytest.terminal import TestShortLogReport from _pytest.tmpdir import TempPathFactory from _pytest.warning_types import PytestAssertRewriteWarning from _pytest.warning_types import PytestCacheWarning @@ -152,6 +153,7 @@ "TempPathFactory", "Testdir", "TestReport", + "TestShortLogReport", "UsageError", "WarningsRecorder", "warns", From a5f37199a95c06088819b8a532d37093c8a2f72e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 13 May 2023 10:34:15 +0300 Subject: [PATCH 066/157] fixtures: inline FixtureRequest._addfinalizer There are no longer any calls to `_addfinalizer` other than this one place, so inline it. --- src/_pytest/fixtures.py | 46 ++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 007245b241c..f389baec382 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -434,7 +434,23 @@ def fixturenames(self) -> List[str]: @property def node(self): """Underlying collection node (depends on current request scope).""" - return self._getscopeitem(self._scope) + scope = self._scope + if scope is Scope.Function: + # This might also be a non-function Item despite its attribute name. + node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem + elif scope is Scope.Package: + # FIXME: _fixturedef is not defined on FixtureRequest (this class), + # but on FixtureRequest (a subclass). + node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] + else: + node = get_scope_node(self._pyfuncitem, scope) + if node is None and scope is Scope.Class: + # Fallback to function item itself. + node = self._pyfuncitem + assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( + scope, self._pyfuncitem + ) + return node def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": fixturedefs = self._arg2fixturedefs.get(argname, None) @@ -518,11 +534,7 @@ def addfinalizer(self, finalizer: Callable[[], object]) -> None: """Add finalizer/teardown function to be called without arguments after the last test within the requesting test context finished execution.""" # XXX usually this method is shadowed by fixturedef specific ones. - self._addfinalizer(finalizer, scope=self.scope) - - def _addfinalizer(self, finalizer: Callable[[], object], scope) -> None: - node = self._getscopeitem(scope) - node.addfinalizer(finalizer) + self.node.addfinalizer(finalizer) def applymarker(self, marker: Union[str, MarkDecorator]) -> None: """Apply a marker to a single test function invocation. @@ -717,28 +729,6 @@ def _factorytraceback(self) -> List[str]: lines.append("%s:%d: def %s%s" % (p, lineno + 1, factory.__name__, args)) return lines - def _getscopeitem( - self, scope: Union[Scope, "_ScopeName"] - ) -> Union[nodes.Item, nodes.Collector]: - if isinstance(scope, str): - scope = Scope(scope) - if scope is Scope.Function: - # This might also be a non-function Item despite its attribute name. - node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem - elif scope is Scope.Package: - # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on FixtureRequest (a subclass). - node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] - else: - node = get_scope_node(self._pyfuncitem, scope) - if node is None and scope is Scope.Class: - # Fallback to function item itself. - node = self._pyfuncitem - assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( - scope, self._pyfuncitem - ) - return node - def __repr__(self) -> str: return "" % (self.node) From ac699e7b25a8d05222fc5b58bd4a1064ff03fa48 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 14 May 2023 21:30:46 +0300 Subject: [PATCH 067/157] fixtures: add type annotations and docstring to `parsefactories` --- src/_pytest/fixtures.py | 44 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index f389baec382..ea2961577dc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -46,6 +46,7 @@ from _pytest.compat import getlocation from _pytest.compat import is_generator from _pytest.compat import NOTSET +from _pytest.compat import NotSetType from _pytest.compat import overload from _pytest.compat import safe_getattr from _pytest.config import _PluggyPlugin @@ -1583,13 +1584,52 @@ def pytest_collection_modifyitems(self, items: List[nodes.Item]) -> None: # Separate parametrized setups. items[:] = reorder_items(items) + @overload def parsefactories( - self, node_or_obj, nodeid=NOTSET, unittest: bool = False + self, + node_or_obj: nodes.Node, + *, + unittest: bool = ..., + ) -> None: + raise NotImplementedError() + + @overload + def parsefactories( # noqa: F811 + self, + node_or_obj: object, + nodeid: Optional[str], + *, + unittest: bool = ..., ) -> None: + raise NotImplementedError() + + def parsefactories( # noqa: F811 + self, + node_or_obj: Union[nodes.Node, object], + nodeid: Union[str, NotSetType, None] = NOTSET, + *, + unittest: bool = False, + ) -> None: + """Collect fixtures from a collection node or object. + + Found fixtures are parsed into `FixtureDef`s and saved. + + If `node_or_object` is a collection node (with an underlying Python + object), the node's object is traversed and the node's nodeid is used to + determine the fixtures' visibilty. `nodeid` must not be specified in + this case. + + If `node_or_object` is an object (e.g. a plugin), the object is + traversed and the given `nodeid` is used to determine the fixtures' + visibility. `nodeid` must be specified in this case; None and "" mean + total visibility. + """ if nodeid is not NOTSET: holderobj = node_or_obj else: - holderobj = node_or_obj.obj + assert isinstance(node_or_obj, nodes.Node) + holderobj = cast(object, node_or_obj.obj) # type: ignore[attr-defined] + assert isinstance(node_or_obj.nodeid, str) nodeid = node_or_obj.nodeid if holderobj in self._holderobjseen: return From 1716d3c9bf46dabba9f6790b4c1ef88305c5990f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 14 May 2023 22:47:29 +0300 Subject: [PATCH 068/157] fixtures: type annotate get_scope_package --- src/_pytest/fixtures.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index ea2961577dc..85039034ea3 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -113,16 +113,19 @@ def pytest_sessionstart(session: "Session") -> None: session._fixturemanager = FixtureManager(session) -def get_scope_package(node, fixturedef: "FixtureDef[object]"): +def get_scope_package( + node: nodes.Item, + fixturedef: "FixtureDef[object]", +) -> Optional[Union[nodes.Item, nodes.Collector]]: import pytest cls = pytest.Package - current = node + current: Optional[Union[nodes.Item, nodes.Collector]] = node fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py") while current and ( type(current) is not cls or fixture_package_name != current.nodeid ): - current = current.parent + current = current.parent # type: ignore[assignment] if current is None: return node.session return current From 5d53447a73940fd6ff2bc53dd58ac61b861d34e8 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 14 May 2023 23:09:16 +0300 Subject: [PATCH 069/157] fixtures: use isinstance in get_scope_package No reason for the exact type equality. --- src/_pytest/fixtures.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 85039034ea3..0462504efaf 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -117,13 +117,12 @@ def get_scope_package( node: nodes.Item, fixturedef: "FixtureDef[object]", ) -> Optional[Union[nodes.Item, nodes.Collector]]: - import pytest + from _pytest.python import Package - cls = pytest.Package current: Optional[Union[nodes.Item, nodes.Collector]] = node fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py") while current and ( - type(current) is not cls or fixture_package_name != current.nodeid + not isinstance(current, Package) or fixture_package_name != current.nodeid ): current = current.parent # type: ignore[assignment] if current is None: From 519f351b4f281473e29fc215f538b74237771ffd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 19 May 2023 14:21:37 +0300 Subject: [PATCH 070/157] pathlib: extract `scandir` utility from `visit` Will be used on its in some upcoming changes, but good on its own. --- src/_pytest/pathlib.py | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 2c9d5870b50..70383e4b504 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -27,6 +27,7 @@ from typing import Dict from typing import Iterable from typing import Iterator +from typing import List from typing import Optional from typing import Set from typing import Tuple @@ -669,30 +670,38 @@ def resolve_package_path(path: Path) -> Optional[Path]: return result +def scandir(path: Union[str, "os.PathLike[str]"]) -> List["os.DirEntry[str]"]: + """Scan a directory recursively, in breadth-first order. + + The returned entries are sorted. + """ + 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. + for entry in s: + try: + entry.is_file() + except OSError as err: + if _ignore_error(err): + continue + raise + entries.append(entry) + entries.sort(key=lambda entry: entry.name) + return entries + + def visit( path: Union[str, "os.PathLike[str]"], recurse: Callable[["os.DirEntry[str]"], bool] ) -> Iterator["os.DirEntry[str]"]: """Walk a directory recursively, in breadth-first order. + The `recurse` predicate determines whether a directory is recursed. + Entries at each directory level are sorted. """ - - # Skip entries with symlink loops and other brokenness, so the caller doesn't - # have to deal with it. - entries = [] - for entry in os.scandir(path): - try: - entry.is_file() - except OSError as err: - if _ignore_error(err): - continue - raise - entries.append(entry) - - entries.sort(key=lambda entry: entry.name) - + entries = scandir(path) yield from entries - for entry in entries: if entry.is_dir() and recurse(entry): yield from visit(entry.path, recurse) From baaa67dfb91444a58b28806bb6719a337454c4bb Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 19 May 2023 14:56:37 +0300 Subject: [PATCH 071/157] python: simplify code in Package.collect() The path of Package is already the `__init__.py` file, and we're already assured it's a file. --- src/_pytest/python.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d04b6fa4ded..9b9d0b7c61e 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -745,11 +745,11 @@ def _collectfile( def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: this_path = self.path.parent - init_module = this_path / "__init__.py" - if init_module.is_file() and path_matches_patterns( - init_module, self.config.getini("python_files") - ): - yield Module.from_parent(self, path=init_module) + + # Always collect the __init__ first. + if path_matches_patterns(self.path, self.config.getini("python_files")): + yield Module.from_parent(self, path=self.path) + pkg_prefixes: Set[Path] = set() for direntry in visit(str(this_path), recurse=self._recurse): path = Path(direntry.path) From 63f258f432198e16aa85a265d59a0513d2a02749 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 20 May 2023 19:46:42 +0300 Subject: [PATCH 072/157] python: fix syntax typo --- src/_pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9b9d0b7c61e..b2f757da486 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -667,7 +667,7 @@ def __init__( config=None, session=None, nodeid=None, - path=Optional[Path], + path: Optional[Path] = None, ) -> None: # NOTE: Could be just the following, but kept as-is for compat. # nodes.FSCollector.__init__(self, fspath, parent=parent) From 9e491f430e5f1e82eb75682342db4e933dd45073 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 May 2023 10:47:02 -0300 Subject: [PATCH 073/157] [automated] Update plugin list (#11027) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 122 ++++++++++++++++--------------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2cb886ed4d1..152c2597d4a 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1255 plugins. +This list contains 1256 plugins. .. only:: not latex @@ -50,7 +50,7 @@ This list contains 1255 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 11, 2023 5 - Production/Stable pytest (<8.0.0,>=6) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 15, 2023 5 - Production/Stable pytest (<8.0.0,>=6) :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -93,7 +93,7 @@ This list contains 1255 plugins. :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. May 20, 2022 N/A pytest (>=7.0.0) - :pypi:`pytest-automock` Pytest plugin for automatical mocks creation Aug 04, 2022 N/A pytest ; extra == 'dev' + :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest @@ -296,7 +296,7 @@ This list contains 1255 plugins. :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Feb 05, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-django` A Django plugin for pytest. Dec 07, 2021 5 - Production/Stable pytest (>=5.4.0) :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) - :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. Mar 18, 2023 4 - Beta pytest + :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) @@ -486,7 +486,7 @@ This list contains 1255 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 11, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 20, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -518,10 +518,10 @@ This list contains 1255 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 06, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 15, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A - :pypi:`pytest-hot-reloading` A pytest plugin to enable a hot reloading daemon. Apr 23, 2023 N/A N/A + :pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) @@ -539,7 +539,7 @@ This list contains 1255 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest Sep 12, 2022 3 - Alpha N/A + :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 16, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -562,7 +562,7 @@ This list contains 1255 plugins. :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 12, 2023 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 03, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 17, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0) @@ -589,7 +589,7 @@ This list contains 1255 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 07, 2022 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Dec 01, 2022 N/A pytest (~=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 13, 2023 4 - Beta pytest + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY May 15, 2023 4 - Beta pytest :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -611,7 +611,7 @@ This list contains 1255 plugins. :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A - :pypi:`pytest-kubernetes` Feb 16, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-kubernetes` May 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A @@ -649,11 +649,11 @@ This list contains 1255 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment May 08, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment May 15, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) - :pypi:`pytest-lsp` Pytest plugin for end-to-end testing of language servers Jan 14, 2023 3 - Alpha pytest + :pypi:`pytest-lsp` pytest plugin for end-to-end testing of language servers May 19, 2023 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -704,7 +704,7 @@ This list contains 1255 plugins. :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest - :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures Dec 07, 2019 5 - Production/Stable pytest (>=2.5.2) + :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Oct 22, 2022 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A @@ -757,7 +757,7 @@ This list contains 1255 plugins. :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 Apr 24, 2023 N/A N/A + :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A @@ -799,7 +799,7 @@ This list contains 1255 plugins. :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) :pypi:`pytest-perf` pytest-perf Jun 23, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-persistence` Pytest tool for persistent objects Mar 28, 2023 N/A N/A + :pypi:`pytest-persistence` Pytest tool for persistent objects May 16, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) @@ -834,7 +834,7 @@ This list contains 1255 plugins. :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 11, 2022 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-pot` A package for enhancing pytest Nov 20, 2022 N/A N/A :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) @@ -1035,7 +1035,7 @@ This list contains 1255 plugins. :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest - :pypi:`pytest-smtpd` package_description May 05, 2023 N/A pytest + :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) @@ -1068,7 +1068,7 @@ This list contains 1255 plugins. :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) - :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 05, 2023 4 - Beta pytest (>=7.0) + :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest @@ -1091,7 +1091,7 @@ This list contains 1255 plugins. :pypi:`pytest-study` A pytest plugin to organize long run tests (named studies) without interfering the regular tests Sep 26, 2017 3 - Alpha pytest (>=2.0) :pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jan 28, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-subtesthack` A hack to explicitly set up and tear down fixtures. Jul 16, 2022 N/A N/A - :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Feb 16, 2023 4 - Beta pytest (>=7.0) + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture May 15, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Aug 29, 2017 N/A N/A :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1102,7 +1102,7 @@ This list contains 1255 plugins. :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A - :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. Apr 13, 2023 3 - Alpha pytest (>=6.2.5) + :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 20, 2023 4 - Beta pytest (>=6.2.5) :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -1121,9 +1121,9 @@ This list contains 1255 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Dec 01, 2022 5 - Production/Stable pytest (!=3.0.2) + :pypi:`pytest-testinfra` Test infrastructures May 19, 2023 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods May 12, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods May 18, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5) @@ -1224,7 +1224,7 @@ This list contains 1255 plugins. :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) - :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Oct 12, 2022 N/A pytest (>=7.0.0) + :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture May 19, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) @@ -1235,6 +1235,7 @@ This list contains 1255 plugins. :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A + :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 19, 2023 N/A N/A :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1242,7 +1243,7 @@ This list contains 1255 plugins. :pypi:`pytest-wiremock` A pytest plugin for programmatically using wiremock in integration tests Mar 27, 2022 N/A pytest (>=7.1.1,<8.0.0) :pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Jan 13, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs May 12, 2023 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs May 19, 2023 5 - Production/Stable pytest (>=6.2.0) :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) @@ -1261,7 +1262,7 @@ This list contains 1255 plugins. :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 08, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 20, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A @@ -1503,7 +1504,7 @@ This list contains 1255 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: May 11, 2023, + *last release*: May 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0.0,>=6) @@ -1804,7 +1805,7 @@ This list contains 1255 plugins. pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. :pypi:`pytest-automock` - *last release*: Aug 04, 2022, + *last release*: May 16, 2023, *status*: N/A, *requires*: pytest ; extra == 'dev' @@ -3225,7 +3226,7 @@ This list contains 1255 plugins. A Django plugin for pytest. :pypi:`pytest-djangoapp` - *last release*: Mar 18, 2023, + *last release*: May 19, 2023, *status*: 4 - Beta, *requires*: pytest @@ -4555,7 +4556,7 @@ This list contains 1255 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: May 11, 2023, + *last release*: May 20, 2023, *status*: N/A, *requires*: N/A @@ -4779,7 +4780,7 @@ This list contains 1255 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 06, 2023, + *last release*: May 15, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -4800,11 +4801,11 @@ This list contains 1255 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Apr 23, 2023, + *last release*: May 18, 2023, *status*: N/A, *requires*: N/A - A pytest plugin to enable a hot reloading daemon. + :pypi:`pytest-hot-test` *last release*: Dec 10, 2022, @@ -4926,7 +4927,7 @@ This list contains 1255 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest-httpserver` - *last release*: Sep 12, 2022, + *last release*: May 16, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -5087,7 +5088,7 @@ This list contains 1255 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Apr 03, 2023, + *last release*: May 17, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5276,7 +5277,7 @@ This list contains 1255 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Mar 13, 2023, + *last release*: May 15, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5430,7 +5431,7 @@ This list contains 1255 plugins. pytest krtech common library :pypi:`pytest-kubernetes` - *last release*: Feb 16, 2023, + *last release*: May 17, 2023, *status*: N/A, *requires*: pytest (>=7.2.1,<8.0.0) @@ -5696,7 +5697,7 @@ This list contains 1255 plugins. :pypi:`pytest-logikal` - *last release*: May 08, 2023, + *last release*: May 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -5724,11 +5725,11 @@ This list contains 1255 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Jan 14, 2023, + *last release*: May 19, 2023, *status*: 3 - Alpha, *requires*: pytest - Pytest plugin for end-to-end testing of language servers + pytest plugin for end-to-end testing of language servers :pypi:`pytest-manual-marker` *last release*: Aug 04, 2022, @@ -6081,9 +6082,9 @@ This list contains 1255 plugins. MongoDB process and client fixtures plugin for Pytest. :pypi:`pytest-mongodb` - *last release*: Dec 07, 2019, + *last release*: May 16, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=2.5.2) + *requires*: N/A pytest plugin for MongoDB fixtures @@ -6452,7 +6453,7 @@ This list contains 1255 plugins. :pypi:`pytest-ogsm-plugin` - *last release*: Apr 24, 2023, + *last release*: May 16, 2023, *status*: N/A, *requires*: N/A @@ -6746,7 +6747,7 @@ This list contains 1255 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-persistence` - *last release*: Mar 28, 2023, + *last release*: May 16, 2023, *status*: N/A, *requires*: N/A @@ -6991,9 +6992,9 @@ This list contains 1255 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Mar 11, 2022, + *last release*: May 20, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest (>=6.2) Postgresql fixtures and fixture factories for Pytest. @@ -8398,11 +8399,11 @@ This list contains 1255 plugins. Send email with pytest execution result :pypi:`pytest-smtpd` - *last release*: May 05, 2023, + *last release*: May 15, 2023, *status*: N/A, *requires*: pytest - package_description + An SMTP server for testing built on aiosmtpd :pypi:`pytest-snail` *last release*: Nov 04, 2019, @@ -8629,7 +8630,7 @@ This list contains 1255 plugins. pytest sqlalchemy plugin for mock :pypi:`pytest-sqlalchemy-session` - *last release*: May 05, 2023, + *last release*: May 19, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0) @@ -8790,7 +8791,7 @@ This list contains 1255 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: Feb 16, 2023, + *last release*: May 15, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0) @@ -8867,8 +8868,8 @@ This list contains 1255 plugins. :pypi:`pytest-tally` - *last release*: Apr 13, 2023, - *status*: 3 - Alpha, + *last release*: May 20, 2023, + *status*: 4 - Beta, *requires*: pytest (>=6.2.5) A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. @@ -9000,7 +9001,7 @@ This list contains 1255 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: Dec 01, 2022, + *last release*: May 19, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=3.0.2) @@ -9014,7 +9015,7 @@ This list contains 1255 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: May 12, 2023, + *last release*: May 18, 2023, *status*: 4 - Beta, *requires*: pytest (<8,>=5) @@ -9721,7 +9722,7 @@ This list contains 1255 plugins. pytest plugin for automatic recording of http stubbed tests :pypi:`pytest-vulture` - *last release*: Oct 12, 2022, + *last release*: May 19, 2023, *status*: N/A, *requires*: pytest (>=7.0.0) @@ -9797,6 +9798,13 @@ This list contains 1255 plugins. Welian API Automation test framework pytest plugin + :pypi:`pytest-when` + *last release*: May 19, 2023, + *status*: N/A, + *requires*: N/A + + Utility which makes mocking more readable and controllable + :pypi:`pytest-whirlwind` *last release*: Jun 12, 2020, *status*: N/A, @@ -9847,7 +9855,7 @@ This list contains 1255 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: May 12, 2023, + *last release*: May 19, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2.0) @@ -9980,7 +9988,7 @@ This list contains 1255 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: May 08, 2023, + *last release*: May 20, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) From 751d726d2106be313eb63134b2a699e2c9b23e7b Mon Sep 17 00:00:00 2001 From: Jarrett Keifer Date: Tue, 23 May 2023 20:06:05 -0700 Subject: [PATCH 074/157] nonpython example now repr all exceptions The definition of `repr_failure` on the `YamlItem` subclass only handled the custom `YamlException` class, which hides all other errors from the user. By adding in the `super` call we ensure all other exception types also appropriately handled by `repr_failure`. --- doc/en/example/nonpython/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index bc39a1f6b20..dd1ebe88d7e 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -38,6 +38,7 @@ def repr_failure(self, excinfo): " no further details known at this point.", ] ) + return super().repr_failure(excinfo) def reportinfo(self): return self.path, 0, f"usecase: {self.name}" From 4f3f36c396b52f8398bc4734ff0c00c57cf1fed1 Mon Sep 17 00:00:00 2001 From: Chris Mahoney <44449504+chrimaho@users.noreply.github.com> Date: Fri, 26 May 2023 20:56:18 +1000 Subject: [PATCH 075/157] Add alias `--config-file` to `-c` (#11036) Fixes #11031 Signed-off-by: Chris Mahoney Co-authored-by: Chris Mahoney --- AUTHORS | 1 + changelog/11031.trivial.rst | 1 + doc/en/reference/reference.rst | 3 ++- src/_pytest/main.py | 7 ++++--- testing/test_config.py | 11 +++++++++++ 5 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 changelog/11031.trivial.rst diff --git a/AUTHORS b/AUTHORS index c9e990bf1bb..30908870783 100644 --- a/AUTHORS +++ b/AUTHORS @@ -72,6 +72,7 @@ Charles Cloud Charles Machalow Charnjit SiNGH (CCSJ) Cheuk Ting Ho +Chris Mahoney Chris Lamb Chris NeJame Chris Rose diff --git a/changelog/11031.trivial.rst b/changelog/11031.trivial.rst new file mode 100644 index 00000000000..fad2cf24d5a --- /dev/null +++ b/changelog/11031.trivial.rst @@ -0,0 +1 @@ +Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 6a5512cc11d..7107218b38b 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1918,7 +1918,8 @@ 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 Load configuration from `file` instead of trying to + -c, --config-file FILE + Load configuration from `FILE` instead of trying to locate one of the implicit configuration files --continue-on-collection-errors Force test execution even if collection errors occur diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 5f8ac46895a..c9a49538095 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -122,11 +122,12 @@ def pytest_addoption(parser: Parser) -> None: ) group._addoption( "-c", - metavar="file", + "--config-file", + metavar="FILE", type=str, dest="inifilename", - help="Load configuration from `file` instead of trying to locate one of the " - "implicit configuration files", + help="Load configuration from `FILE` instead of trying to locate one of the " + "implicit configuration files.", ) group._addoption( "--continue-on-collection-errors", diff --git a/testing/test_config.py b/testing/test_config.py index 6754cd15bf4..1291e85f9dd 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -514,6 +514,8 @@ def pytest_addoption(parser): ) config = pytester.parseconfig("-c", "custom.ini") assert config.getini("custom") == "1" + config = pytester.parseconfig("--config-file", "custom.ini") + assert config.getini("custom") == "1" pytester.makefile( ".cfg", @@ -524,6 +526,8 @@ def pytest_addoption(parser): ) config = pytester.parseconfig("-c", "custom_tool_pytest_section.cfg") assert config.getini("custom") == "1" + config = pytester.parseconfig("--config-file", "custom_tool_pytest_section.cfg") + assert config.getini("custom") == "1" pytester.makefile( ".toml", @@ -536,6 +540,8 @@ def pytest_addoption(parser): ) config = pytester.parseconfig("-c", "custom.toml") assert config.getini("custom") == "1" + config = pytester.parseconfig("--config-file", "custom.toml") + assert config.getini("custom") == "1" def test_absolute_win32_path(self, pytester: Pytester) -> None: temp_ini_file = pytester.makefile( @@ -550,6 +556,8 @@ def test_absolute_win32_path(self, pytester: Pytester) -> None: temp_ini_file_norm = normpath(str(temp_ini_file)) ret = pytest.main(["-c", temp_ini_file_norm]) assert ret == ExitCode.OK + ret = pytest.main(["--config-file", temp_ini_file_norm]) + assert ret == ExitCode.OK class TestConfigAPI: @@ -1907,6 +1915,9 @@ def test_pytest_custom_cfg_unsupported(self, pytester: Pytester) -> None: with pytest.raises(pytest.fail.Exception): pytester.runpytest("-c", "custom.cfg") + with pytest.raises(pytest.fail.Exception): + pytester.runpytest("--config-file", "custom.cfg") + class TestPytestPluginsVariable: def test_pytest_plugins_in_non_top_level_conftest_unsupported( From 5313d50e187ab4dc9f267c88c15ff2a7d757fb05 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 28 May 2023 00:22:05 +0000 Subject: [PATCH 076/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 132 ++++++++++++++++++------------- 1 file changed, 78 insertions(+), 54 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 152c2597d4a..fafc8c876c7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1256 plugins. +This list contains 1259 plugins. .. only:: not latex @@ -38,7 +38,7 @@ This list contains 1256 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 18, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 23, 2023 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -213,7 +213,7 @@ This list contains 1256 plugins. :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A - :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts Mar 18, 2022 4 - Beta N/A + :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 22, 2023 4 - Beta N/A :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest :pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 21, 2023 4 - Beta pytest (>=3.10) :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A @@ -221,14 +221,14 @@ This list contains 1256 plugins. :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-cov` Pytest plugin for measuring coverage. Sep 28, 2022 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0) :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Apr 20, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types May 25, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -304,7 +304,7 @@ This list contains 1256 plugins. :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Feb 09, 2022 3 - Alpha N/A + :pypi:`pytest-django-ifactory` A model instance factory for pytest-django May 21, 2023 5 - Production/Stable N/A :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A @@ -486,7 +486,7 @@ This list contains 1256 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 20, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 22, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -499,7 +499,7 @@ This list contains 1256 plugins. :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-goldie` A plugin to support golden tests with pytest. Apr 12, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A @@ -518,7 +518,7 @@ This list contains 1256 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 15, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 24, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A @@ -539,7 +539,7 @@ This list contains 1256 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 16, 2023 3 - Alpha N/A + :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -569,7 +569,7 @@ This list contains 1256 plugins. :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) :pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A - :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0) + :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest May 22, 2023 N/A pytest (>=5.2) :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 09, 2023 4 - Beta pytest @@ -649,7 +649,7 @@ This list contains 1256 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment May 15, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment May 27, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -680,9 +680,9 @@ This list contains 1256 plugins. :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A - :pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) + :pypi:`pytest-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin May 04, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin May 25, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) @@ -695,7 +695,7 @@ This list contains 1256 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 03, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 23, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -825,6 +825,7 @@ This list contains 1256 plugins. :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Dec 24, 2022 5 - Production/Stable pytest (>=6.0.1) :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A + :pypi:`pytest-pokie` Pokie plugin for pytest May 22, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A :pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest :pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A @@ -910,11 +911,12 @@ This list contains 1256 plugins. :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A + :pypi:`pytest-regex` Select pytest tests with regular expressions May 23, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0) :pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A - :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Dec 31, 2022 5 - Production/Stable pytest (>=7) + :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) @@ -929,10 +931,10 @@ This list contains 1256 plugins. :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Apr 26, 2023 3 - Alpha pytest + :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Apr 21, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal May 24, 2023 N/A pytest (>=3.8.0) :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -989,18 +991,19 @@ This list contains 1256 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A + :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Apr 15, 2023 3 - Alpha pytest (>=6.2) @@ -1102,7 +1105,7 @@ This list contains 1256 plugins. :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A - :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 20, 2023 4 - Beta pytest (>=6.2.5) + :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -1121,7 +1124,7 @@ This list contains 1256 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures May 19, 2023 5 - Production/Stable pytest (!=3.0.2) + :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) :pypi:`pytest-testmon` selects tests affected by changed files and methods May 18, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) @@ -1208,7 +1211,7 @@ This list contains 1256 plugins. :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest :pypi:`pytest-valgrind` May 19, 2021 N/A N/A - :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) + :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) @@ -1235,7 +1238,7 @@ This list contains 1256 plugins. :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 19, 2023 N/A N/A + :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 22, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1262,7 +1265,7 @@ This list contains 1256 plugins. :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 20, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 22, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A @@ -1420,7 +1423,7 @@ This list contains 1256 plugins. :pypi:`pytest-alembic` - *last release*: Apr 18, 2023, + *last release*: May 23, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -2645,7 +2648,7 @@ This list contains 1256 plugins. Package stands for pytest plugin to upload results into Confluence page. :pypi:`pytest-console-scripts` - *last release*: Mar 18, 2022, + *last release*: May 22, 2023, *status*: 4 - Beta, *requires*: N/A @@ -2701,7 +2704,7 @@ This list contains 1256 plugins. count erros and send email :pypi:`pytest-cov` - *last release*: Sep 28, 2022, + *last release*: May 24, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=4.6) @@ -2750,7 +2753,7 @@ This list contains 1256 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Apr 20, 2023, + *last release*: May 25, 2023, *status*: N/A, *requires*: N/A @@ -3282,8 +3285,8 @@ This list contains 1256 plugins. Cleanup your Haystack indexes between tests :pypi:`pytest-django-ifactory` - *last release*: Feb 09, 2022, - *status*: 3 - Alpha, + *last release*: May 21, 2023, + *status*: 5 - Production/Stable, *requires*: N/A A model instance factory for pytest-django @@ -4556,7 +4559,7 @@ This list contains 1256 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: May 20, 2023, + *last release*: May 22, 2023, *status*: N/A, *requires*: N/A @@ -4647,7 +4650,7 @@ This list contains 1256 plugins. Plugin for pytest that offloads expected outputs to data files :pypi:`pytest-goldie` - *last release*: Apr 12, 2023, + *last release*: May 23, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.5.0) @@ -4780,7 +4783,7 @@ This list contains 1256 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 15, 2023, + *last release*: May 24, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -4927,7 +4930,7 @@ This list contains 1256 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest-httpserver` - *last release*: May 16, 2023, + *last release*: May 22, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -5137,9 +5140,9 @@ This list contains 1256 plugins. Organizing pytests by integration or not :pypi:`pytest-integration-mark` - *last release*: Jul 19, 2021, + *last release*: May 22, 2023, *status*: N/A, - *requires*: pytest (>=5.2,<7.0) + *requires*: pytest (>=5.2) Automatic integration test marking and excluding plugin for pytest @@ -5697,7 +5700,7 @@ This list contains 1256 plugins. :pypi:`pytest-logikal` - *last release*: May 15, 2023, + *last release*: May 27, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -5914,9 +5917,9 @@ This list contains 1256 plugins. Pytest to Slack reporting plugin :pypi:`pytest-metadata` - *last release*: Oct 30, 2022, + *last release*: May 27, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0,<8.0.0) + *requires*: pytest>=7.0.0 pytest plugin for test session metadata @@ -5928,7 +5931,7 @@ This list contains 1256 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: May 04, 2023, + *last release*: May 25, 2023, *status*: N/A, *requires*: pytest @@ -6019,7 +6022,7 @@ This list contains 1256 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: May 03, 2023, + *last release*: May 23, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6928,6 +6931,13 @@ This list contains 1256 plugins. Pytest plugin to define functions you test with special marks for better navigation and reports + :pypi:`pytest-pokie` + *last release*: May 22, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + Pokie plugin for pytest + :pypi:`pytest-polarion-cfme` *last release*: Nov 13, 2017, *status*: 3 - Alpha, @@ -7523,6 +7533,13 @@ This list contains 1256 plugins. Conveniently run pytest with a dot-formatted test reference. + :pypi:`pytest-regex` + *last release*: May 23, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.5.0) + + Select pytest tests with regular expressions + :pypi:`pytest-regex-dependency` *last release*: Jun 12, 2022, *status*: N/A, @@ -7552,7 +7569,7 @@ This list contains 1256 plugins. a pytest plugin that sorts tests using "before" and "after" markers :pypi:`pytest-relaxed` - *last release*: Dec 31, 2022, + *last release*: May 23, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=7) @@ -7657,7 +7674,7 @@ This list contains 1256 plugins. A plugin to report summarized results in a table format :pypi:`pytest-reportlog` - *last release*: Apr 26, 2023, + *last release*: May 22, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -7678,7 +7695,7 @@ This list contains 1256 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Apr 21, 2023, + *last release*: May 24, 2023, *status*: N/A, *requires*: pytest (>=3.8.0) @@ -8077,7 +8094,7 @@ This list contains 1256 plugins. :pypi:`pytest-sbase` - *last release*: May 12, 2023, + *last release*: May 25, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8126,7 +8143,7 @@ This list contains 1256 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: May 12, 2023, + *last release*: May 25, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8160,6 +8177,13 @@ This list contains 1256 plugins. A pytest plugin to send testrun information to Sentry.io + :pypi:`pytest-sequence-markers` + *last release*: May 23, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + Pytest plugin for sequencing markers for execution of tests + :pypi:`pytest-server-fixtures` *last release*: May 28, 2019, *status*: 5 - Production/Stable, @@ -8868,7 +8892,7 @@ This list contains 1256 plugins. :pypi:`pytest-tally` - *last release*: May 20, 2023, + *last release*: May 22, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.2.5) @@ -9001,7 +9025,7 @@ This list contains 1256 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: May 19, 2023, + *last release*: May 21, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=3.0.2) @@ -9610,9 +9634,9 @@ This list contains 1256 plugins. :pypi:`pytest-variables` - *last release*: Mar 27, 2022, + *last release*: May 27, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0,<8.0.0) + *requires*: pytest>=7.0.0 pytest plugin for providing variables to tests/fixtures @@ -9799,9 +9823,9 @@ This list contains 1256 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: May 19, 2023, + *last release*: May 22, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest>=7.3.1 Utility which makes mocking more readable and controllable @@ -9988,7 +10012,7 @@ This list contains 1256 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: May 20, 2023, + *last release*: May 22, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) From dd667336ce0b55b430452e78cd57ba2c0a769066 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Apr 2023 18:51:49 +0300 Subject: [PATCH 077/157] nodes: apply same traceback filtering for chained exceptions as main exception Fix #1904. --- changelog/1904.bugfix.rst | 1 + src/_pytest/_code/code.py | 22 +++++++++++++----- src/_pytest/nodes.py | 7 ++++-- testing/code/test_excinfo.py | 45 ++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 changelog/1904.bugfix.rst diff --git a/changelog/1904.bugfix.rst b/changelog/1904.bugfix.rst new file mode 100644 index 00000000000..3e1a292152b --- /dev/null +++ b/changelog/1904.bugfix.rst @@ -0,0 +1 @@ +Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message). diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 5148dcdbeb4..9b051332baf 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -635,7 +635,9 @@ def getrepr( showlocals: bool = False, style: "_TracebackStyle" = "long", abspath: bool = False, - tbfilter: bool = True, + tbfilter: Union[ + bool, Callable[["ExceptionInfo[BaseException]"], Traceback] + ] = True, funcargs: bool = False, truncate_locals: bool = True, chain: bool = True, @@ -652,9 +654,15 @@ def getrepr( :param bool abspath: If paths should be changed to absolute or left unchanged. - :param bool tbfilter: - Hide entries that contain a local variable ``__tracebackhide__==True``. - Ignored if ``style=="native"``. + :param tbfilter: + A filter for traceback entries. + + * If false, don't hide any entries. + * If true, hide internal entries and entries that contain a local + variable ``__tracebackhide__ = True``. + * If a callable, delegates the filtering to the callable. + + Ignored if ``style`` is ``"native"``. :param bool funcargs: Show fixtures ("funcargs" for legacy purposes) per traceback entry. @@ -719,7 +727,7 @@ class FormattedExcinfo: showlocals: bool = False style: "_TracebackStyle" = "long" abspath: bool = True - tbfilter: bool = True + tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True funcargs: bool = False truncate_locals: bool = True chain: bool = True @@ -881,7 +889,9 @@ def _makepath(self, path: Union[Path, str]) -> str: def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback": traceback = excinfo.traceback - if self.tbfilter: + if callable(self.tbfilter): + traceback = self.tbfilter(excinfo) + elif self.tbfilter: traceback = traceback.filter(excinfo) if isinstance(excinfo.value, RecursionError): diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 1a1a47a28d4..dbd6b0a4273 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -450,10 +450,13 @@ def _repr_failure_py( style = "value" if isinstance(excinfo.value, FixtureLookupError): return excinfo.value.formatrepr() + + tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] if self.config.getoption("fulltrace", False): style = "long" + tbfilter = False else: - excinfo.traceback = self._traceback_filter(excinfo) + tbfilter = self._traceback_filter if style == "auto": style = "long" # XXX should excinfo.getrepr record all data and toterminal() process it? @@ -484,7 +487,7 @@ def _repr_failure_py( abspath=abspath, showlocals=self.config.getoption("showlocals", False), style=style, - tbfilter=False, # pruned already, or in --fulltrace mode. + tbfilter=tbfilter, truncate_locals=truncate_locals, ) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index bda6cd4cdd0..88aa5f0f154 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1603,3 +1603,48 @@ def test(): result.stdout.fnmatch_lines(["*ZeroDivisionError: division by zero"]) if tbstyle not in ("line", "native"): result.stdout.fnmatch_lines(["All traceback entries are hidden.*"]) + + +def test_hidden_entries_of_chained_exceptions_are_not_shown(pytester: Pytester) -> None: + """Hidden entries of chained exceptions are not shown (#1904).""" + p = pytester.makepyfile( + """ + def g1(): + __tracebackhide__ = True + str.does_not_exist + + def f3(): + __tracebackhide__ = True + 1 / 0 + + def f2(): + try: + f3() + except Exception: + g1() + + def f1(): + __tracebackhide__ = True + f2() + + def test(): + f1() + """ + ) + result = pytester.runpytest(str(p), "--tb=short") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*.py:11: in f2", + " f3()", + "E ZeroDivisionError: division by zero", + "", + "During handling of the above exception, another exception occurred:", + "*.py:20: in test", + " f1()", + "*.py:13: in f2", + " g1()", + "E AttributeError:*'does_not_exist'", + ], + consecutive=True, + ) From ec752537ea01e46ab51bd2787786ce9a5db99597 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 07:55:13 +0200 Subject: [PATCH 078/157] build(deps): Bump pytest-cov in /testing/plugins_integration (#11051) Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.0.0 to 4.1.0. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v4.1.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index bcc3ad9877c..b5a6c654460 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -2,7 +2,7 @@ anyio[curio,trio]==3.6.2 django==4.2.1 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 -pytest-cov==4.0.0 +pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 pytest-html==3.2.0 From fbfd4b50050080413c8faca5368b9cb9b1ac9313 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 07:55:42 +0200 Subject: [PATCH 079/157] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#11050) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 3.6.2 to 3.7.0. - [Changelog](https://github.com/agronholm/anyio/blob/3.7.0/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/3.6.2...3.7.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index b5a6c654460..0d30ab96fe0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==3.6.2 +anyio[curio,trio]==3.7.0 django==4.2.1 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 From fc538c5766a1c67bfcd704288279ceac5e20070a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 29 May 2023 22:38:36 +0300 Subject: [PATCH 080/157] cacheprovider: fix file-skipping feature for files in packages `--lf` has a feature where if a certain `Module` (python file) does not contain any failed tests, it is skipped entirely at the collector level instead of being collected and each item skipped individually. When this happens the collection summary looks like this: run-last-failure: rerun previous 1 failure (skipped 1 file) However, this feature didn't work for `Module`s inside of `Package`s, only for those directly beneath the `Session`. Fix #11054. --- changelog/11054.bugfix.rst | 1 + src/_pytest/cacheprovider.py | 2 +- testing/test_cacheprovider.py | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 changelog/11054.bugfix.rst diff --git a/changelog/11054.bugfix.rst b/changelog/11054.bugfix.rst new file mode 100644 index 00000000000..a8ee04fe304 --- /dev/null +++ b/changelog/11054.bugfix.rst @@ -0,0 +1 @@ +Fixed ``--last-failed``'s "(skipped N files)" functionality for files inside of packages (directories with `__init__.py` files). diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 89a4a55f8fc..84ca2c68814 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -219,7 +219,7 @@ def __init__(self, lfplugin: "LFPlugin") -> None: @hookimpl(hookwrapper=True) def pytest_make_collect_report(self, collector: nodes.Collector): - if isinstance(collector, Session): + if isinstance(collector, (Session, Package)): out = yield res: CollectReport = out.get_result() diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index ee2fe1845df..7c6606e2b7a 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -420,7 +420,13 @@ def test_fail(val): result = pytester.runpytest() result.stdout.fnmatch_lines(["*1 failed in*"]) - def test_terminal_report_lastfailed(self, pytester: Pytester) -> None: + @pytest.mark.parametrize("parent", ("session", "package")) + def test_terminal_report_lastfailed(self, pytester: Pytester, parent: str) -> None: + if parent == "package": + pytester.makepyfile( + __init__="", + ) + test_a = pytester.makepyfile( test_a=""" def test_a1(): pass From 7c231baa6400a653eb322705ffffb6385dead3dc Mon Sep 17 00:00:00 2001 From: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> Date: Tue, 30 May 2023 06:06:13 -0400 Subject: [PATCH 081/157] Add warning when testpaths is set but paths are not found by glob (#11044) Closes #11013 --------- Co-authored-by: Ran Benita --- AUTHORS | 1 + changelog/11013.improvement.rst | 1 + src/_pytest/config/__init__.py | 9 +++++++++ testing/test_warnings.py | 14 ++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 changelog/11013.improvement.rst diff --git a/AUTHORS b/AUTHORS index 30908870783..77d64712683 100644 --- a/AUTHORS +++ b/AUTHORS @@ -197,6 +197,7 @@ Justice Ndou Justyna Janczyszyn Kale Kundert Kamran Ahmad +Kenny Y Karl O. Pinc Karthikeyan Singaravelan Katarzyna Jachim diff --git a/changelog/11013.improvement.rst b/changelog/11013.improvement.rst new file mode 100644 index 00000000000..fe3ece93c23 --- /dev/null +++ b/changelog/11013.improvement.rst @@ -0,0 +1 @@ +Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6df06f7b281..23b17b9a697 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1382,6 +1382,15 @@ def parse(self, args: List[str], addopts: bool = True) -> None: args = [] for path in testpaths: args.extend(sorted(glob.iglob(path, recursive=True))) + if testpaths and not args: + warning_text = ( + "No files were found in testpaths; " + "consider removing or adjusting your testpaths configuration. " + "Searching recursively from the current directory instead." + ) + self.issue_config_time_warning( + PytestConfigWarning(warning_text), stacklevel=3 + ) if not args: source = Config.ArgsSource.INCOVATION_DIR args = [str(self.invocation_params.dir)] diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 7b716bb4546..a1ecba2476e 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -777,6 +777,20 @@ def test_it(): ) +def test_warning_on_testpaths_not_found(pytester: Pytester) -> None: + # Check for warning when testpaths set, but not found by glob + pytester.makeini( + """ + [pytest] + testpaths = absent + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + ["*ConfigWarning: No files were found in testpaths*", "*1 warning*"] + ) + + def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None: # Some platforms (notably PyPy) don't have tracemalloc. # We choose to explicitly not skip this in case tracemalloc is not From 4da9026766b3b6586a12a815a9713457c6567ec1 Mon Sep 17 00:00:00 2001 From: theirix Date: Tue, 30 May 2023 15:35:33 +0300 Subject: [PATCH 082/157] Handle microseconds with custom logging.Formatter (#11047) Added handling of %f directive to print microseconds in log format options, such as log-date-format. It is impossible to do with a standard logging.Formatter because it uses time.strftime which doesn't know about milliseconds and %f. In this PR I added a custom Formatter which converts LogRecord to a datetime.datetime object and formats it with %f flag. This behaviour is enabled only if a microsecond flag is specified in a format string. Also added a few tests to check the standard and changed behavior. Closes #10991 --- AUTHORS | 1 + changelog/10991.improvement.rst | 1 + src/_pytest/logging.py | 28 ++++++++- testing/logging/test_reporting.py | 97 +++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 changelog/10991.improvement.rst diff --git a/AUTHORS b/AUTHORS index 77d64712683..42936552f1d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -131,6 +131,7 @@ Eric Siegerman Erik Aronesty Erik M. Bray Evan Kepner +Evgeny Seliverstov Fabien Zarifian Fabio Zadrozny Felix Hofstätter diff --git a/changelog/10991.improvement.rst b/changelog/10991.improvement.rst new file mode 100644 index 00000000000..768c08e554c --- /dev/null +++ b/changelog/10991.improvement.rst @@ -0,0 +1 @@ +Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 95774dd1472..6381e86b01d 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -5,7 +5,11 @@ import re from contextlib import contextmanager from contextlib import nullcontext +from datetime import datetime +from datetime import timedelta +from datetime import timezone from io import StringIO +from logging import LogRecord from pathlib import Path from typing import AbstractSet from typing import Dict @@ -53,7 +57,25 @@ def _remove_ansi_escape_sequences(text: str) -> str: return _ANSI_ESCAPE_SEQ.sub("", text) -class ColoredLevelFormatter(logging.Formatter): +class DatetimeFormatter(logging.Formatter): + """A logging formatter which formats record with + :func:`datetime.datetime.strftime` formatter instead of + :func:`time.strftime` in case of microseconds in format string. + """ + + def formatTime(self, record: LogRecord, datefmt=None) -> str: + if datefmt and "%f" in datefmt: + ct = self.converter(record.created) + tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone) + # Construct `datetime.datetime` object from `struct_time` + # and msecs information from `record` + dt = datetime(*ct[0:6], microsecond=round(record.msecs * 1000), tzinfo=tz) + return dt.strftime(datefmt) + # Use `logging.Formatter` for non-microsecond formats + return super().formatTime(record, datefmt) + + +class ColoredLevelFormatter(DatetimeFormatter): """A logging formatter which colorizes the %(levelname)..s part of the log format passed to __init__.""" @@ -625,7 +647,7 @@ def __init__(self, config: Config) -> None: config, "log_file_date_format", "log_date_format" ) - log_file_formatter = logging.Formatter( + log_file_formatter = DatetimeFormatter( log_file_format, datefmt=log_file_date_format ) self.log_file_handler.setFormatter(log_file_formatter) @@ -669,7 +691,7 @@ def _create_formatter(self, log_format, log_date_format, auto_indent): create_terminal_writer(self._config), log_format, log_date_format ) else: - formatter = logging.Formatter(log_format, log_date_format) + formatter = DatetimeFormatter(log_format, log_date_format) formatter._style = PercentStyleMultiline( formatter._style._fmt, auto_indent=auto_indent diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index ae2f53277fb..14b77236ab2 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1234,3 +1234,100 @@ def test_log_cli_works(caplog): "WARNING disabled:test_log_disabling_works_with_log_cli.py:7 This string will be suppressed." ) assert not result.stderr.lines + + +def test_without_date_format_log(pytester: Pytester) -> None: + """Check that date is not printed by default.""" + pytester.makepyfile( + """ + import logging + + logger = logging.getLogger(__name__) + + def test_foo(): + logger.warning('text') + assert False + """ + ) + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines( + ["WARNING test_without_date_format_log:test_without_date_format_log.py:6 text"] + ) + + +def test_date_format_log(pytester: Pytester) -> None: + """Check that log_date_format affects output.""" + pytester.makepyfile( + """ + import logging + + logger = logging.getLogger(__name__) + + def test_foo(): + logger.warning('text') + assert False + """ + ) + pytester.makeini( + """ + [pytest] + log_format=%(asctime)s; %(levelname)s; %(message)s + log_date_format=%Y-%m-%d %H:%M:%S + """ + ) + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}; WARNING; text"]) + + +def test_date_format_percentf_log(pytester: Pytester) -> None: + """Make sure that microseconds are printed in log.""" + pytester.makepyfile( + """ + import logging + + logger = logging.getLogger(__name__) + + def test_foo(): + logger.warning('text') + assert False + """ + ) + pytester.makeini( + """ + [pytest] + log_format=%(asctime)s; %(levelname)s; %(message)s + log_date_format=%Y-%m-%d %H:%M:%S.%f + """ + ) + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}; WARNING; text"]) + + +def test_date_format_percentf_tz_log(pytester: Pytester) -> None: + """Make sure that timezone and microseconds are properly formatted together.""" + pytester.makepyfile( + """ + import logging + + logger = logging.getLogger(__name__) + + def test_foo(): + logger.warning('text') + assert False + """ + ) + pytester.makeini( + """ + [pytest] + log_format=%(asctime)s; %(levelname)s; %(message)s + log_date_format=%Y-%m-%d %H:%M:%S.%f%z + """ + ) + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.re_match_lines( + [r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}[+-][0-9\.]+; WARNING; text"] + ) From 9e1add75f771904ac124bbd0e313a77febe62ce4 Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Tue, 30 May 2023 16:59:24 +0200 Subject: [PATCH 083/157] Fix warlus operator behavior when called by a function (#11041) In #10758 we introduced the support for the use of the walrus operator in the test cases. There was a case which was not handled that caused a bug report #11028. This PR aims to fix the issue and also to improve how the walrus operator is handled in the AssertionRewriter class. Closes #11028 --- changelog/11028.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 25 +++++++-- testing/test_assertrewrite.py | 90 ++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 changelog/11028.bugfix.rst diff --git a/changelog/11028.bugfix.rst b/changelog/11028.bugfix.rst new file mode 100644 index 00000000000..9efc04ba69f --- /dev/null +++ b/changelog/11028.bugfix.rst @@ -0,0 +1 @@ +Fixed bug in assertion rewriting where a variable assigned with the walrus operator could not be used later in a function call. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 8b182347052..ab8169da2ef 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -996,7 +996,9 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: ] ): pytest_temp = self.variable() - self.variables_overwrite[v.left.target.id] = pytest_temp + self.variables_overwrite[ + v.left.target.id + ] = v.left # type:ignore[assignment] v.left.target.id = pytest_temp self.push_format_context() res, expl = self.visit(v) @@ -1037,10 +1039,19 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: new_args = [] new_kwargs = [] for arg in call.args: + if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite: + arg = self.variables_overwrite[arg.id] # type:ignore[assignment] res, expl = self.visit(arg) arg_expls.append(expl) new_args.append(res) for keyword in call.keywords: + if ( + isinstance(keyword.value, ast.Name) + and keyword.value.id in self.variables_overwrite + ): + keyword.value = self.variables_overwrite[ + keyword.value.id + ] # type:ignore[assignment] res, expl = self.visit(keyword.value) new_kwargs.append(ast.keyword(keyword.arg, res)) if keyword.arg: @@ -1075,7 +1086,13 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: self.push_format_context() # We first check if we have overwritten a variable in the previous assert if isinstance(comp.left, ast.Name) and comp.left.id in self.variables_overwrite: - comp.left.id = self.variables_overwrite[comp.left.id] + comp.left = self.variables_overwrite[ + comp.left.id + ] # type:ignore[assignment] + if isinstance(comp.left, namedExpr): + self.variables_overwrite[ + comp.left.target.id + ] = comp.left # type:ignore[assignment] left_res, left_expl = self.visit(comp.left) if isinstance(comp.left, (ast.Compare, ast.BoolOp)): left_expl = f"({left_expl})" @@ -1093,7 +1110,9 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: and next_operand.target.id == left_res.id ): next_operand.target.id = self.variable() - self.variables_overwrite[left_res.id] = next_operand.target.id + self.variables_overwrite[ + left_res.id + ] = next_operand # type:ignore[assignment] next_res, next_expl = self.visit(next_operand) if isinstance(next_operand, (ast.Compare, ast.BoolOp)): next_expl = f"({next_expl})" diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 8d944140307..245241af2b2 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1436,6 +1436,96 @@ def test_walrus_operator_not_override_value(): assert result.ret == 0 +@pytest.mark.skipif( + sys.version_info < (3, 8), reason="walrus operator not available in py<38" +) +class TestIssue11028: + def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + def test_in_string(): + assert (obj := "foo") in obj + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + def test_assertion_walrus_operator_in_operand_json_dumps( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + import json + + def test_json_encoder(): + assert (obj := "foo") in json.dumps(obj) + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + def test_assertion_walrus_operator_equals_operand_function( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + def f(a): + return a + + def test_call_other_function_arg(): + assert (obj := "foo") == f(obj) + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + def test_assertion_walrus_operator_equals_operand_function_keyword_arg( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + def f(a='test'): + return a + + def test_call_other_function_k_arg(): + assert (obj := "foo") == f(a=obj) + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + def test_assertion_walrus_operator_equals_operand_function_arg_as_function( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + def f(a='test'): + return a + + def test_function_of_function(): + assert (obj := "foo") == f(f(obj)) + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + def test_assertion_walrus_operator_gt_operand_function( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + """ + def add_one(a): + return a + 1 + + def test_gt(): + assert (obj := 4) > add_one(obj) + """ + ) + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"]) + + @pytest.mark.skipif( sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems" ) From 4a1bba25b9ad23dccc00c695ffb4050b6ddb4189 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 May 2023 18:42:37 +0300 Subject: [PATCH 084/157] config: fallback confcutdir to rootpath if inipath is not set Currently, if `--confcutdir` is not set, `inipath.parent` is used, and if `initpath` is not set, then `confcutdir` is None, which means there is no cutoff. Having no cutoff is not great, it means we potentially start probing stuff all the way up to the filesystem root directory. So let's add another fallback, to `rootpath`, which is always something reasonable. --- changelog/11043.improvement.rst | 3 +++ src/_pytest/config/__init__.py | 7 +++++-- testing/test_config.py | 17 +++++++++++++++++ testing/test_conftest.py | 8 +++++++- 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 changelog/11043.improvement.rst diff --git a/changelog/11043.improvement.rst b/changelog/11043.improvement.rst new file mode 100644 index 00000000000..1fe0361d7f9 --- /dev/null +++ b/changelog/11043.improvement.rst @@ -0,0 +1,3 @@ +When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir`. +Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. +If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6df06f7b281..c62be613523 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1261,8 +1261,11 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None: _pytest.deprecated.STRICT_OPTION, stacklevel=2 ) - if self.known_args_namespace.confcutdir is None and self.inipath is not None: - confcutdir = str(self.inipath.parent) + if self.known_args_namespace.confcutdir is None: + if self.inipath is not None: + confcutdir = str(self.inipath.parent) + else: + confcutdir = str(self.rootpath) self.known_args_namespace.confcutdir = confcutdir try: self.hook.pytest_load_initial_conftests( diff --git a/testing/test_config.py b/testing/test_config.py index 1291e85f9dd..cdeb67aceff 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -179,6 +179,23 @@ def test_toml_parse_error(self, pytester: Pytester) -> None: assert result.ret != 0 result.stderr.fnmatch_lines("ERROR: *pyproject.toml: Invalid statement*") + def test_confcutdir_default_without_configfile(self, pytester: Pytester) -> None: + # If --confcutdir is not specified, and there is no configfile, default + # to the roothpath. + sub = pytester.mkdir("sub") + os.chdir(sub) + config = pytester.parseconfigure() + assert config.pluginmanager._confcutdir == sub + + def test_confcutdir_default_with_configfile(self, pytester: Pytester) -> None: + # If --confcutdir is not specified, and there is a configfile, default + # to the configfile's directory. + pytester.makeini("[pytest]") + sub = pytester.mkdir("sub") + os.chdir(sub) + config = pytester.parseconfigure() + assert config.pluginmanager._confcutdir == pytester.path + @pytest.mark.xfail(reason="probably not needed") def test_confcutdir(self, pytester: Pytester) -> None: sub = pytester.mkdir("sub") diff --git a/testing/test_conftest.py b/testing/test_conftest.py index d6abca5368f..c64bd11d4ed 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -594,7 +594,13 @@ def test_parsefactories_relative_node_ids( print("pytestarg : %s" % testarg) print("expected pass : %s" % expect_ntests_passed) os.chdir(dirs[chdir]) - reprec = pytester.inline_run(testarg, "-q", "--traceconfig") + reprec = pytester.inline_run( + testarg, + "-q", + "--traceconfig", + "--confcutdir", + pytester.path, + ) reprec.assertoutcome(passed=expect_ntests_passed) From c76ae74bd79e8db9ff08996a86bc4f1cfdc1be48 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 30 May 2023 09:29:19 +0300 Subject: [PATCH 085/157] cacheprovider: fix file-skipping functionality across packages Continuation of fc538c5766a1c67bfcd704288279ceac5e20070a. Fixes #11054 again. --- src/_pytest/cacheprovider.py | 26 +++++++++++++++++++------- testing/test_cacheprovider.py | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 84ca2c68814..3d4fb1d6c2e 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -226,10 +226,18 @@ def pytest_make_collect_report(self, collector: nodes.Collector): # Sort any lf-paths to the beginning. lf_paths = self.lfplugin._last_failed_paths + # Use stable sort to priorize last failed. + def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: + # Package.path is the __init__.py file, we need the directory. + if isinstance(node, Package): + path = node.path.parent + else: + path = node.path + return path in lf_paths + res.result = sorted( res.result, - # use stable sort to priorize last failed - key=lambda x: x.path in lf_paths, + key=sort_key, reverse=True, ) return @@ -272,9 +280,8 @@ def __init__(self, lfplugin: "LFPlugin") -> None: def pytest_make_collect_report( self, collector: nodes.Collector ) -> Optional[CollectReport]: - # Packages are Modules, but _last_failed_paths only contains - # test-bearing paths and doesn't try to include the paths of their - # packages, so don't filter them. + # Packages are Modules, but we only want to skip test-bearing Modules, + # so don't filter Packages. if isinstance(collector, Module) and not isinstance(collector, Package): if collector.path not in self.lfplugin._last_failed_paths: self.lfplugin._skipped_files += 1 @@ -305,9 +312,14 @@ def __init__(self, config: Config) -> None: ) def get_last_failed_paths(self) -> Set[Path]: - """Return a set with all Paths()s of the previously failed nodeids.""" + """Return a set with all Paths of the previously failed nodeids and + their parents.""" rootpath = self.config.rootpath - result = {rootpath / nodeid.split("::")[0] for nodeid in self.lastfailed} + result = set() + for nodeid in self.lastfailed: + path = rootpath / nodeid.split("::")[0] + result.add(path) + result.update(path.parents) return {x for x in result if x.exists()} def pytest_report_collectionfinish(self) -> Optional[str]: diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 7c6606e2b7a..cb8011036ef 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -854,6 +854,33 @@ def test_3(): pass ] ) + def test_lastfailed_skip_collection_with_nesting(self, pytester: Pytester) -> None: + """Check that file skipping works even when the file with failures is + nested at a different level of the collection tree.""" + pytester.makepyfile( + **{ + "test_1.py": """ + def test_1(): pass + """, + "pkg/__init__.py": "", + "pkg/test_2.py": """ + def test_2(): assert False + """, + } + ) + # first run + result = pytester.runpytest() + result.stdout.fnmatch_lines(["collected 2 items", "*1 failed*1 passed*"]) + # second run - test_1.py is skipped. + result = pytester.runpytest("--lf") + result.stdout.fnmatch_lines( + [ + "collected 1 item", + "run-last-failure: rerun previous 1 failure (skipped 1 file)", + "*= 1 failed in *", + ] + ) + def test_lastfailed_with_known_failures_not_being_selected( self, pytester: Pytester ) -> None: From 3de43e51025a75369c2560623c5e7fc50c0b5137 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Jun 2023 16:06:35 +0300 Subject: [PATCH 086/157] python: remove redundant methods from Package They are already inherited exactly the same from FSCollector. --- src/_pytest/python.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 94f000939b9..3b1253cf4b7 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -57,7 +57,6 @@ from _pytest.config import hookimpl from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest -from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import INSTANCE_COLLECTOR from _pytest.deprecated import NOSE_SUPPORT_METHOD from _pytest.fixtures import FuncFixtureInfo @@ -700,14 +699,6 @@ def setup(self) -> None: func = partial(_call_with_optional_argument, teardown_module, self.obj) self.addfinalizer(func) - def gethookproxy(self, fspath: "os.PathLike[str]"): - warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2) - return self.session.gethookproxy(fspath) - - def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool: - warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2) - return self.session.isinitpath(path) - def _recurse(self, direntry: "os.DirEntry[str]") -> bool: if direntry.name == "__pycache__": return False From fda8024622df64802f9670bfe2ba658b40f6674d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Jun 2023 11:41:36 +0300 Subject: [PATCH 087/157] cacheprovider: make file-skipping work with any File, not just Modules No reason for `--lf`'s whole-file-skipping feature to not for for non-Python files. Fix #11068. --- changelog/11068.bugfix.rst | 1 + src/_pytest/cacheprovider.py | 8 ++++---- testing/conftest.py | 2 +- testing/test_cacheprovider.py | 22 ++++++++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 changelog/11068.bugfix.rst diff --git a/changelog/11068.bugfix.rst b/changelog/11068.bugfix.rst new file mode 100644 index 00000000000..45cdb105fb4 --- /dev/null +++ b/changelog/11068.bugfix.rst @@ -0,0 +1 @@ +Fixed the ``--last-failed`` whole-file skipping functionality ("skipped N files") for :ref:`non-python test files `. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 3d4fb1d6c2e..855716d8199 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -27,7 +27,7 @@ from _pytest.fixtures import fixture from _pytest.fixtures import FixtureRequest from _pytest.main import Session -from _pytest.python import Module +from _pytest.nodes import File from _pytest.python import Package from _pytest.reports import TestReport @@ -242,7 +242,7 @@ def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: ) return - elif isinstance(collector, Module): + elif isinstance(collector, File): if collector.path in self.lfplugin._last_failed_paths: out = yield res = out.get_result() @@ -280,9 +280,9 @@ def __init__(self, lfplugin: "LFPlugin") -> None: def pytest_make_collect_report( self, collector: nodes.Collector ) -> Optional[CollectReport]: - # Packages are Modules, but we only want to skip test-bearing Modules, + # Packages are Files, but we only want to skip test-bearing Files, # so don't filter Packages. - if isinstance(collector, Module) and not isinstance(collector, Package): + if isinstance(collector, File) and not isinstance(collector, Package): if collector.path not in self.lfplugin._last_failed_paths: self.lfplugin._skipped_files += 1 diff --git a/testing/conftest.py b/testing/conftest.py index a83552fd256..8e77fcae5ab 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -105,7 +105,7 @@ def get_write_msg(self, idx): @pytest.fixture -def dummy_yaml_custom_test(pytester: Pytester): +def dummy_yaml_custom_test(pytester: Pytester) -> None: """Writes a conftest file that collects and executes a dummy yaml test. Taken from the docs, but stripped down to the bare minimum, useful for diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index cb8011036ef..6f3cccbf1c2 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1085,6 +1085,28 @@ def test_packages(self, pytester: Pytester) -> None: result = pytester.runpytest("--lf") result.assert_outcomes(failed=3) + def test_non_python_file_skipped( + self, + pytester: Pytester, + dummy_yaml_custom_test: None, + ) -> None: + pytester.makepyfile( + **{ + "test_bad.py": """def test_bad(): assert False""", + }, + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines(["collected 2 items", "* 1 failed, 1 passed in *"]) + + result = pytester.runpytest("--lf") + result.stdout.fnmatch_lines( + [ + "collected 1 item", + "run-last-failure: rerun previous 1 failure (skipped 1 file)", + "* 1 failed in *", + ] + ) + class TestNewFirst: def test_newfirst_usecase(self, pytester: Pytester) -> None: From 1daa8129c656af9352f25f9ace9cedcc7a262386 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 4 Jun 2023 00:26:58 +0000 Subject: [PATCH 088/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 152 ++++++++++++++++--------------- 1 file changed, 80 insertions(+), 72 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index fafc8c876c7..ca885180451 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1259 plugins. +This list contains 1260 plugins. .. only:: not latex @@ -83,7 +83,7 @@ This list contains 1259 plugins. :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest-asyncio` Pytest support for asyncio Mar 19, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 10, 2023 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. May 31, 2023 N/A N/A :pypi:`pytest-asyncio-network-simulator` pytest-asyncio-network-simulator: Plugin for pytest for simulator the network in tests Jul 31, 2018 3 - Alpha pytest (<3.7.0,>=3.3.2) :pypi:`pytest-async-mongodb` pytest plugin for async MongoDB Oct 18, 2017 5 - Production/Stable pytest (>=2.5.2) :pypi:`pytest-async-sqlalchemy` Database testing fixtures using the SQLAlchemy asyncio API Oct 07, 2021 4 - Beta pytest (>=6.0.0) @@ -213,7 +213,7 @@ This list contains 1259 plugins. :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A - :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 22, 2023 4 - Beta N/A + :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest :pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 21, 2023 4 - Beta pytest (>=3.10) :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A @@ -228,7 +228,7 @@ This list contains 1259 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types May 25, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 02, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -268,6 +268,7 @@ This list contains 1259 plugins. :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) + :pypi:`pytest-dbt` Unit test dbt models with standard python tooling May 31, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. May 03, 2023 N/A pytest (>=6.2.5) ; extra == 'test' @@ -366,13 +367,13 @@ This list contains 1259 plugins. :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` pytest embedded plugin Apr 11, 2023 N/A pytest (>=7.0) - :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects Apr 11, 2023 N/A N/A - :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project Apr 11, 2023 N/A N/A - :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag Apr 11, 2023 N/A N/A - :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip Apr 11, 2023 N/A N/A - :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports Apr 11, 2023 N/A N/A - :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports Apr 11, 2023 N/A N/A + :pypi:`pytest-embedded` pytest embedded plugin May 31, 2023 N/A pytest (>=7.0) + :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects May 31, 2023 N/A N/A + :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project May 31, 2023 N/A N/A + :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag May 31, 2023 N/A N/A + :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip May 31, 2023 N/A N/A + :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports May 31, 2023 N/A N/A + :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports May 31, 2023 N/A N/A :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) @@ -486,7 +487,7 @@ This list contains 1259 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 22, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 31, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -518,7 +519,7 @@ This list contains 1259 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 24, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 02, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A @@ -540,7 +541,7 @@ This list contains 1259 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jun 03, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -573,7 +574,7 @@ This list contains 1259 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 09, 2023 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 13, 2023 5 - Production/Stable pytest (<7.2.0,>=6) + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -589,7 +590,7 @@ This list contains 1259 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 07, 2022 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Dec 01, 2022 N/A pytest (~=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY May 15, 2023 4 - Beta pytest + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY May 29, 2023 4 - Beta pytest :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -620,7 +621,7 @@ This list contains 1259 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Mar 11, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. May 28, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -649,7 +650,7 @@ This list contains 1259 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment May 27, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment Jun 03, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -671,7 +672,7 @@ This list contains 1259 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Aug 06, 2022 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. May 28, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Dec 02, 2022 N/A pytest>=7.2 @@ -797,7 +798,7 @@ This list contains 1259 plugins. :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) - :pypi:`pytest-perf` pytest-perf Jun 23, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects May 16, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) @@ -863,7 +864,7 @@ This list contains 1259 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" May 10, 2023 N/A pytest + :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 02, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) @@ -881,7 +882,7 @@ This list contains 1259 plugins. :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 26, 2022 5 - Production/Stable pytest (>=6.2.3) + :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins May 31, 2023 5 - Production/Stable pytest (>=6.2.5) :pypi:`pytest-qml` Run QML Tests with pytest Dec 02, 2020 4 - Beta pytest (>=6.0.0) :pypi:`pytest-qr` pytest plugin to generate test result QR codes Nov 25, 2021 4 - Beta N/A :pypi:`pytest-qt` pytest support for PyQt and PySide applications Oct 25, 2022 5 - Production/Stable pytest (>=3.0.0) @@ -911,7 +912,7 @@ This list contains 1259 plugins. :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A - :pypi:`pytest-regex` Select pytest tests with regular expressions May 23, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0) :pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A @@ -945,7 +946,7 @@ This list contains 1259 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 09, 2023 5 - Production/Stable pytest (>=5.3) :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest May 05, 2023 N/A pytest (~=4.6) ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jun 01, 2023 N/A pytest (~=4.6) ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 @@ -991,14 +992,14 @@ This list contains 1259 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 02, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) - :pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A + :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 02, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1227,18 +1228,18 @@ This list contains 1259 plugins. :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) - :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture May 19, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` May 11, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Continiously runs pytest on changes in \*.py files Dec 11, 2022 3 - Alpha N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 03, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 22, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 31, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1260,12 +1261,12 @@ This list contains 1259 plugins. :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-xvfb` A pytest plugin to run Xvfb for tests. Jun 09, 2020 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1) :pypi:`pytest-yaml` This plugin is used to load yaml output to your test using pytest framework. Oct 05, 2018 N/A pytest - :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml May 28, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 22, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 30, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A @@ -1738,7 +1739,7 @@ This list contains 1259 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: Feb 10, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A @@ -2648,9 +2649,9 @@ This list contains 1259 plugins. Package stands for pytest plugin to upload results into Confluence page. :pypi:`pytest-console-scripts` - *last release*: May 22, 2023, + *last release*: May 31, 2023, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest (>=4.0.0) Pytest plugin for testing console scripts @@ -2753,7 +2754,7 @@ This list contains 1259 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: May 25, 2023, + *last release*: Jun 02, 2023, *status*: N/A, *requires*: N/A @@ -3032,6 +3033,13 @@ This list contains 1259 plugins. + :pypi:`pytest-dbt` + *last release*: May 31, 2023, + *status*: 2 - Pre-Alpha, + *requires*: pytest (>=7.0.0,<8.0.0) + + Unit test dbt models with standard python tooling + :pypi:`pytest-dbt-adapter` *last release*: Nov 24, 2021, *status*: N/A, @@ -3719,49 +3727,49 @@ This list contains 1259 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: pytest (>=7.0) pytest embedded plugin :pypi:`pytest-embedded-arduino` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for Arduino projects :pypi:`pytest-embedded-idf` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for esp-idf project :pypi:`pytest-embedded-jtag` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing with jtag :pypi:`pytest-embedded-qemu` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for qemu, not target chip :pypi:`pytest-embedded-serial` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing serial ports :pypi:`pytest-embedded-serial-esp` - *last release*: Apr 11, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A @@ -4559,7 +4567,7 @@ This list contains 1259 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: May 22, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: N/A @@ -4783,7 +4791,7 @@ This list contains 1259 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 24, 2023, + *last release*: Jun 02, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -4937,7 +4945,7 @@ This list contains 1259 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Apr 19, 2023, + *last release*: Jun 03, 2023, *status*: N/A, *requires*: pytest (>=7.2.0,<8.0.0) @@ -5168,7 +5176,7 @@ This list contains 1259 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Apr 13, 2023, + *last release*: Jun 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<7.2.0,>=6) @@ -5280,7 +5288,7 @@ This list contains 1259 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: May 15, 2023, + *last release*: May 29, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5497,7 +5505,7 @@ This list contains 1259 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Mar 11, 2023, + *last release*: May 28, 2023, *status*: N/A, *requires*: pytest (>=7.2.1,<8.0.0) @@ -5700,7 +5708,7 @@ This list contains 1259 plugins. :pypi:`pytest-logikal` - *last release*: May 27, 2023, + *last release*: Jun 03, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -5854,7 +5862,7 @@ This list contains 1259 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Aug 06, 2022, + *last release*: May 28, 2023, *status*: 4 - Beta, *requires*: pytest (!=6.0.0,<8,>=3.3.2) @@ -6736,11 +6744,11 @@ This list contains 1259 plugins. Change the exit code of pytest test sessions when a required percent of tests pass. :pypi:`pytest-perf` - *last release*: Jun 23, 2022, + *last release*: Jun 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' - pytest-perf + Run performance tests against the mainline code. :pypi:`pytest-performance` *last release*: Sep 11, 2020, @@ -7198,7 +7206,7 @@ This list contains 1259 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: May 10, 2023, + *last release*: Jun 02, 2023, *status*: N/A, *requires*: pytest @@ -7324,9 +7332,9 @@ This list contains 1259 plugins. Pytest plugin for uploading test results to your QA Touch Testrun. :pypi:`pytest-qgis` - *last release*: Jun 26, 2022, + *last release*: May 31, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.3) + *requires*: pytest (>=6.2.5) A pytest plugin for testing QGIS python plugins @@ -7534,7 +7542,7 @@ This list contains 1259 plugins. Conveniently run pytest with a dot-formatted test reference. :pypi:`pytest-regex` - *last release*: May 23, 2023, + *last release*: May 29, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.5.0) @@ -7772,7 +7780,7 @@ This list contains 1259 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: May 05, 2023, + *last release*: Jun 01, 2023, *status*: N/A, *requires*: pytest (~=4.6) ; python_version == "2.7" @@ -8094,7 +8102,7 @@ This list contains 1259 plugins. :pypi:`pytest-sbase` - *last release*: May 25, 2023, + *last release*: Jun 02, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8136,14 +8144,14 @@ This list contains 1259 plugins. A pytest plugin which allows to (de-)select tests from a file. :pypi:`pytest-selenium` - *last release*: Sep 21, 2022, + *last release*: May 28, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.0.0,<7.0.0) + *requires*: pytest>=6.0.0 pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: May 25, 2023, + *last release*: Jun 02, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9746,7 +9754,7 @@ This list contains 1259 plugins. pytest plugin for automatic recording of http stubbed tests :pypi:`pytest-vulture` - *last release*: May 19, 2023, + *last release*: Jun 01, 2023, *status*: N/A, *requires*: pytest (>=7.0.0) @@ -9788,11 +9796,11 @@ This list contains 1259 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Dec 11, 2022, - *status*: 3 - Alpha, + *last release*: Jun 03, 2023, + *status*: 4 - Beta, *requires*: N/A - Continiously runs pytest on changes in \*.py files + Automatically rerun your tests on file modifications :pypi:`pytest-wdl` *last release*: Nov 17, 2020, @@ -9823,7 +9831,7 @@ This list contains 1259 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: May 22, 2023, + *last release*: May 31, 2023, *status*: N/A, *requires*: pytest>=7.3.1 @@ -9977,11 +9985,11 @@ This list contains 1259 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-xvfb` - *last release*: Jun 09, 2020, + *last release*: May 29, 2023, *status*: 4 - Beta, *requires*: pytest (>=2.8.1) - A pytest plugin to run Xvfb for tests. + A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-yaml` *last release*: Oct 05, 2018, @@ -9991,7 +9999,7 @@ This list contains 1259 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Mar 17, 2023, + *last release*: May 28, 2023, *status*: N/A, *requires*: pytest>=7.2.0 @@ -10012,7 +10020,7 @@ This list contains 1259 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: May 22, 2023, + *last release*: May 30, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) From 313b61471f47d7d95402110ed5960c1ffacd3157 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 4 Jun 2023 00:32:28 +0300 Subject: [PATCH 089/157] main: change pkg_roots to work with `Path`s instead of string paths - Works better on Windows (case sensitivity) - Simpler code --- src/_pytest/main.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index c9a49538095..8f07daeec76 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -686,8 +686,8 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # are not collected more than once. matchnodes_cache: Dict[Tuple[Type[nodes.Collector], str], CollectReport] = {} - # Dirnames of pkgs with dunder-init files. - pkg_roots: Dict[str, Package] = {} + # Directories of pkgs with dunder-init files. + pkg_roots: Dict[Path, Package] = {} for argpath, names in self._initial_parts: self.trace("processing argument", (argpath, names)) @@ -708,7 +708,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: col = self._collectfile(pkginit, handle_dupes=False) if col: if isinstance(col[0], Package): - pkg_roots[str(parent)] = col[0] + pkg_roots[parent] = col[0] node_cache1[col[0].path] = [col[0]] # If it's a directory argument, recurse and look for any Subpackages. @@ -717,7 +717,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: assert not names, f"invalid arg {(argpath, names)!r}" seen_dirs: Set[Path] = set() - for direntry in visit(str(argpath), self._recurse): + for direntry in visit(argpath, self._recurse): if not direntry.is_file(): continue @@ -732,8 +732,8 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: for x in self._collectfile(pkginit): yield x if isinstance(x, Package): - pkg_roots[str(dirpath)] = x - if str(dirpath) in pkg_roots: + pkg_roots[dirpath] = x + if dirpath in pkg_roots: # Do not collect packages here. continue @@ -750,7 +750,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: if argpath in node_cache1: col = node_cache1[argpath] else: - collect_root = pkg_roots.get(str(argpath.parent), self) + collect_root = pkg_roots.get(argpath.parent, self) col = collect_root._collectfile(argpath, handle_dupes=False) if col: node_cache1[argpath] = col From 85c5bd26b6d94dca423c2c0c54717750eac81cae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 12:06:55 +0200 Subject: [PATCH 090/157] build(deps): Bump pytest-xvfb in /testing/plugins_integration (#11079) Bumps [pytest-xvfb](https://github.com/The-Compiler/pytest-xvfb) from 2.0.0 to 3.0.0. - [Changelog](https://github.com/The-Compiler/pytest-xvfb/blob/master/CHANGELOG.rst) - [Commits](https://github.com/The-Compiler/pytest-xvfb/compare/v2.0.0...v3.0.0) --- updated-dependencies: - dependency-name: pytest-xvfb dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 0d30ab96fe0..7db8cc0abdb 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -12,4 +12,4 @@ pytest-sugar==0.9.7 pytest-trio==0.7.0 pytest-twisted==1.14.0 twisted==22.8.0 -pytest-xvfb==2.0.0 +pytest-xvfb==3.0.0 From ae38b076da99ea0d4092a4be604ccc4b0f73d8af Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Jun 2023 17:08:46 +0300 Subject: [PATCH 091/157] main: move norecursedir check to main's pytest_ignore_collect Fix #11081 --- changelog/11081.improvement.rst | 1 + src/_pytest/main.py | 9 ++++++--- src/_pytest/python.py | 3 --- 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 changelog/11081.improvement.rst diff --git a/changelog/11081.improvement.rst b/changelog/11081.improvement.rst new file mode 100644 index 00000000000..227e478d4bc --- /dev/null +++ b/changelog/11081.improvement.rst @@ -0,0 +1 @@ +The :confval:`norecursedir` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 8f07daeec76..155d4300e2c 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -400,6 +400,12 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo allow_in_venv = config.getoption("collect_in_virtualenv") if not allow_in_venv and _in_venv(collection_path): return True + + if collection_path.is_dir(): + norecursepatterns = config.getini("norecursedirs") + if any(fnmatch_ex(pat, collection_path) for pat in norecursepatterns): + return True + return None @@ -563,9 +569,6 @@ def _recurse(self, direntry: "os.DirEntry[str]") -> bool: ihook = self.gethookproxy(fspath.parent) if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): return False - norecursepatterns = self.config.getini("norecursedirs") - if any(fnmatch_ex(pat, fspath) for pat in norecursepatterns): - return False return True def _collectfile( diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 3b1253cf4b7..ad847c8afe2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -706,9 +706,6 @@ def _recurse(self, direntry: "os.DirEntry[str]") -> bool: ihook = self.session.gethookproxy(fspath.parent) if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): return False - norecursepatterns = self.config.getini("norecursedirs") - if any(fnmatch_ex(pat, fspath) for pat in norecursepatterns): - return False return True def _collectfile( From ee8baa2676c7f4ecb7e9e64db354b2cee75a18ff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 12:13:38 +0300 Subject: [PATCH 092/157] [pre-commit.ci] pre-commit autoupdate (#11084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/setup-cfg-fmt: v2.2.0 → v2.3.0](https://github.com/asottile/setup-cfg-fmt/compare/v2.2.0...v2.3.0) --- .pre-commit-config.yaml | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af6cd262300..4ecaee56ced 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,7 +47,7 @@ repos: - id: pyupgrade args: [--py37-plus] - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.2.0 + rev: v2.3.0 hooks: - id: setup-cfg-fmt args: ["--max-py-version=3.11", "--include-version-classifiers"] diff --git a/setup.cfg b/setup.cfg index 56dadae7bf5..1f99a801994 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ long_description_content_type = text/x-rst url = https://docs.pytest.org/en/latest/ author = Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others license = MIT -license_file = LICENSE +license_files = LICENSE platforms = unix, linux, osx, cygwin, win32 classifiers = Development Status :: 6 - Mature From 1790f172283abe9c22d715731445e22e546b844d Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Tue, 6 Jun 2023 06:15:57 -0300 Subject: [PATCH 093/157] Introduced a hardcoded list of project to include as plugins beyond those found by their names. (#11077) --- scripts/update-plugin-list.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 34d1c8bb639..ea7e7986e15 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -17,7 +17,9 @@ =========== PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically. Packages classified as inactive are excluded. +automatically together with a manually-maintained list in `the source +code `_. +Packages classified as inactive are excluded. .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the @@ -33,6 +35,9 @@ "Development Status :: 6 - Mature", "Development Status :: 7 - Inactive", ) +ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins + "logassert", +} def escape_rst(text: str) -> str: @@ -52,18 +57,18 @@ def iter_plugins(): regex = r">([\d\w-]*)" response = requests.get("https://pypi.org/simple") - matches = list( - match - for match in re.finditer(regex, response.text) - if match.groups()[0].startswith("pytest-") - ) + match_names = (match.groups()[0] for match in re.finditer(regex, response.text)) + plugin_names = [ + name + for name in match_names + if name.startswith("pytest-") or name in ADDITIONAL_PROJECTS + ] - for match in tqdm(matches, smoothing=0): - name = match.groups()[0] + for name in tqdm(plugin_names, smoothing=0): response = requests.get(f"https://pypi.org/pypi/{name}/json") if response.status_code == 404: - # Some packages, like pytest-azurepipelines42, are included in https://pypi.org/simple but - # return 404 on the JSON API. Skip. + # Some packages, like pytest-azurepipelines42, are included in https://pypi.org/simple + # but return 404 on the JSON API. Skip. continue response.raise_for_status() info = response.json()["info"] From fc9cbbd4c4d76ca20963370cfd800395b9a87495 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Tue, 6 Jun 2023 14:05:44 +0000 Subject: [PATCH 094/157] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 76 ++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ca885180451..40f9b5baed7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -5,19 +5,22 @@ Plugin List =========== PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically. Packages classified as inactive are excluded. +automatically together with a manually-maintained list in `the source +code `_. +Packages classified as inactive are excluded. .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1260 plugins. +This list contains 1261 plugins. .. only:: not latex =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ name summary last release status requires =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ + :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) @@ -305,7 +308,7 @@ This list contains 1260 plugins. :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-django-ifactory` A model instance factory for pytest-django May 21, 2023 5 - Production/Stable N/A + :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Jun 06, 2023 5 - Production/Stable N/A :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A @@ -367,13 +370,13 @@ This list contains 1260 plugins. :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` pytest embedded plugin May 31, 2023 N/A pytest (>=7.0) - :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects May 31, 2023 N/A N/A - :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project May 31, 2023 N/A N/A - :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag May 31, 2023 N/A N/A - :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip May 31, 2023 N/A N/A - :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports May 31, 2023 N/A N/A - :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports May 31, 2023 N/A N/A + :pypi:`pytest-embedded` pytest embedded plugin Jun 06, 2023 N/A pytest (>=7.0) + :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects Jun 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project Jun 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag Jun 06, 2023 N/A N/A + :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip Jun 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports Jun 06, 2023 N/A N/A + :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports Jun 06, 2023 N/A N/A :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) @@ -519,7 +522,7 @@ This list contains 1260 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 02, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 06, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A @@ -650,7 +653,7 @@ This list contains 1260 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jun 03, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment Jun 04, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -675,7 +678,7 @@ This list contains 1260 plugins. :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. May 28, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A - :pypi:`pytest-memray` A simple plugin to use with pytest Dec 02, 2022 N/A pytest>=7.2 + :pypi:`pytest-memray` A simple plugin to use with pytest Jun 06, 2023 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) @@ -730,7 +733,7 @@ This list contains 1260 plugins. :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Apr 18, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 05, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -928,7 +931,7 @@ This list contains 1260 plugins. :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 08, 2021 4 - Beta N/A + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 05, 2023 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1239,7 +1242,7 @@ This list contains 1260 plugins. :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 31, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jun 05, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1283,6 +1286,13 @@ This list contains 1260 plugins. .. only:: latex + :pypi:`logassert` + *last release*: May 20, 2022, + *status*: 5 - Production/Stable, + *requires*: N/A + + Simple but powerful assertion and verification of logged lines. + :pypi:`pytest-abq` *last release*: Apr 07, 2023, *status*: N/A, @@ -3293,7 +3303,7 @@ This list contains 1260 plugins. Cleanup your Haystack indexes between tests :pypi:`pytest-django-ifactory` - *last release*: May 21, 2023, + *last release*: Jun 06, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3727,49 +3737,49 @@ This list contains 1260 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: May 31, 2023, + *last release*: Jun 06, 2023, *status*: N/A, *requires*: pytest (>=7.0) pytest embedded plugin :pypi:`pytest-embedded-arduino` - *last release*: May 31, 2023, - *status*: N/A, + *last release*: Jun 06, 2023, + *status*: 5 - Production/Stable, *requires*: N/A pytest embedded plugin for Arduino projects :pypi:`pytest-embedded-idf` - *last release*: May 31, 2023, - *status*: N/A, + *last release*: Jun 06, 2023, + *status*: 5 - Production/Stable, *requires*: N/A pytest embedded plugin for esp-idf project :pypi:`pytest-embedded-jtag` - *last release*: May 31, 2023, + *last release*: Jun 06, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing with jtag :pypi:`pytest-embedded-qemu` - *last release*: May 31, 2023, - *status*: N/A, + *last release*: Jun 06, 2023, + *status*: 5 - Production/Stable, *requires*: N/A pytest embedded plugin for qemu, not target chip :pypi:`pytest-embedded-serial` - *last release*: May 31, 2023, + *last release*: Jun 06, 2023, *status*: N/A, *requires*: N/A pytest embedded plugin for testing serial ports :pypi:`pytest-embedded-serial-esp` - *last release*: May 31, 2023, + *last release*: Jun 06, 2023, *status*: N/A, *requires*: N/A @@ -4791,7 +4801,7 @@ This list contains 1260 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 02, 2023, + *last release*: Jun 06, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -5708,7 +5718,7 @@ This list contains 1260 plugins. :pypi:`pytest-logikal` - *last release*: Jun 03, 2023, + *last release*: Jun 04, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -5883,7 +5893,7 @@ This list contains 1260 plugins. Estimates memory consumption of test functions :pypi:`pytest-memray` - *last release*: Dec 02, 2022, + *last release*: Jun 06, 2023, *status*: N/A, *requires*: pytest>=7.2 @@ -6268,7 +6278,7 @@ This list contains 1260 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Apr 18, 2023, + *last release*: Jun 05, 2023, *status*: N/A, *requires*: pytest (>=3.5.0) @@ -7654,7 +7664,7 @@ This list contains 1260 plugins. Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Jun 08, 2021, + *last release*: Jun 05, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9831,7 +9841,7 @@ This list contains 1260 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: May 31, 2023, + *last release*: Jun 05, 2023, *status*: N/A, *requires*: pytest>=7.3.1 From 9335a0b4453dbb08a07b6ac1b33d1ed3d17c45a5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 10 May 2023 10:36:09 +0300 Subject: [PATCH 095/157] Avoid ast deprecation warnings on Python 3.12 Fix #10977. --- src/_pytest/assertion/rewrite.py | 49 +++++++++++++++++++------------- src/_pytest/mark/expression.py | 8 +++++- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ab8169da2ef..ab83fee32b2 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -46,8 +46,14 @@ if sys.version_info >= (3, 8): namedExpr = ast.NamedExpr + astNameConstant = ast.Constant + astStr = ast.Constant + astNum = ast.Constant else: namedExpr = ast.Expr + astNameConstant = ast.NameConstant + astStr = ast.Str + astNum = ast.Num assertstate_key = StashKey["AssertionState"]() @@ -680,9 +686,12 @@ def run(self, mod: ast.Module) -> None: if ( expect_docstring and isinstance(item, ast.Expr) - and isinstance(item.value, ast.Str) + and isinstance(item.value, astStr) ): - doc = item.value.s + if sys.version_info >= (3, 8): + doc = item.value.value + else: + doc = item.value.s if self.is_rewrite_disabled(doc): return expect_docstring = False @@ -814,7 +823,7 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: current = self.stack.pop() if self.stack: self.explanation_specifiers = self.stack[-1] - keys = [ast.Str(key) for key in current.keys()] + keys = [astStr(key) for key in current.keys()] format_dict = ast.Dict(keys, list(current.values())) form = ast.BinOp(expl_expr, ast.Mod(), format_dict) name = "@py_format" + str(next(self.variable_counter)) @@ -868,16 +877,16 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: negation = ast.UnaryOp(ast.Not(), top_condition) if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook - msg = self.pop_format_context(ast.Str(explanation)) + msg = self.pop_format_context(astStr(explanation)) # Failed if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) gluestr = "\n>assert " else: - assertmsg = ast.Str("") + assertmsg = astStr("") gluestr = "assert " - err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg) + err_explanation = ast.BinOp(astStr(gluestr), ast.Add(), msg) err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation) err_name = ast.Name("AssertionError", ast.Load()) fmt = self.helper("_format_explanation", err_msg) @@ -893,8 +902,8 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: hook_call_pass = ast.Expr( self.helper( "_call_assertion_pass", - ast.Num(assert_.lineno), - ast.Str(orig), + astNum(assert_.lineno), + astStr(orig), fmt_pass, ) ) @@ -913,7 +922,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: variables = [ ast.Name(name, ast.Store()) for name in self.format_variables ] - clear_format = ast.Assign(variables, ast.NameConstant(None)) + clear_format = ast.Assign(variables, astNameConstant(None)) self.statements.append(clear_format) else: # Original assertion rewriting @@ -924,9 +933,9 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: assertmsg = self.helper("_format_assertmsg", assert_.msg) explanation = "\n>assert " + explanation else: - assertmsg = ast.Str("") + assertmsg = astStr("") explanation = "assert " + explanation - template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) + template = ast.BinOp(assertmsg, ast.Add(), astStr(explanation)) msg = self.pop_format_context(template) fmt = self.helper("_format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) @@ -938,7 +947,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] - clear = ast.Assign(variables, ast.NameConstant(None)) + clear = ast.Assign(variables, astNameConstant(None)) self.statements.append(clear) # Fix locations (line numbers/column offsets). for stmt in self.statements: @@ -952,20 +961,20 @@ def visit_NamedExpr(self, name: namedExpr) -> Tuple[namedExpr, str]: # thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) target_id = name.target.id # type: ignore[attr-defined] - inlocs = ast.Compare(ast.Str(target_id), [ast.In()], [locs]) + inlocs = ast.Compare(astStr(target_id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) - expr = ast.IfExp(test, self.display(name), ast.Str(target_id)) + expr = ast.IfExp(test, self.display(name), astStr(target_id)) return name, self.explanation_param(expr) def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]: # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) - inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs]) + inlocs = ast.Compare(astStr(name.id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) - expr = ast.IfExp(test, self.display(name), ast.Str(name.id)) + expr = ast.IfExp(test, self.display(name), astStr(name.id)) return name, self.explanation_param(expr) def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: @@ -1003,7 +1012,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) - expl_format = self.pop_format_context(ast.Str(expl)) + expl_format = self.pop_format_context(astStr(expl)) call = ast.Call(app, [expl_format], []) self.expl_stmts.append(ast.Expr(call)) if i < levels: @@ -1015,7 +1024,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: self.statements = body = inner self.statements = save self.expl_stmts = fail_save - expl_template = self.helper("_format_boolop", expl_list, ast.Num(is_or)) + expl_template = self.helper("_format_boolop", expl_list, astNum(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl) @@ -1118,9 +1127,9 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: next_expl = f"({next_expl})" results.append(next_res) sym = BINOP_MAP[op.__class__] - syms.append(ast.Str(sym)) + syms.append(astStr(sym)) expl = f"{left_expl} {sym} {next_expl}" - expls.append(ast.Str(expl)) + expls.append(astStr(expl)) res_expr = ast.Compare(left_res, [op], [next_res]) self.statements.append(ast.Assign([store_names[i]], res_expr)) left_res, left_expl = next_res, next_expl diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index f82a81d44c5..9287bcee50c 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -18,6 +18,7 @@ import dataclasses import enum import re +import sys import types from typing import Callable from typing import Iterator @@ -26,6 +27,11 @@ from typing import Optional from typing import Sequence +if sys.version_info >= (3, 8): + astNameConstant = ast.Constant +else: + astNameConstant = ast.NameConstant + __all__ = [ "Expression", @@ -132,7 +138,7 @@ def reject(self, expected: Sequence[TokenType]) -> NoReturn: def expression(s: Scanner) -> ast.Expression: if s.accept(TokenType.EOF): - ret: ast.expr = ast.NameConstant(False) + ret: ast.expr = astNameConstant(False) else: ret = expr(s) s.accept(TokenType.EOF, reject=True) From fc3b5b2610ef667eb80b847cd7f5d4d6bfef79fc Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 23 May 2023 15:10:46 +0300 Subject: [PATCH 096/157] testing: install setuptools to fix pkg_resources import in a test Since Python 3.12, setuptools is no longer installed by default in venvs. We have a test which uses it, so add it to the testing extra. --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 1f99a801994..2eee4cf5311 100644 --- a/setup.cfg +++ b/setup.cfg @@ -73,6 +73,7 @@ testing = nose pygments>=2.7.2 requests + setuptools xmlschema [options.package_data] From 3e65a461c7293510753ed960a04d72e263f93bb0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Apr 2023 10:20:19 +0300 Subject: [PATCH 097/157] ci: start testing Python 3.12-dev --- .github/workflows/test.yml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cd1ffdbf9d4..5435949fced 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,6 +43,7 @@ jobs: "windows-py39", "windows-py310", "windows-py311", + "windows-py312", "ubuntu-py37", "ubuntu-py37-pluggy", @@ -51,12 +52,13 @@ jobs: "ubuntu-py39", "ubuntu-py310", "ubuntu-py311", + "ubuntu-py312", "ubuntu-pypy3", "macos-py37", - "macos-py38", "macos-py39", "macos-py310", + "macos-py312", "docs", "doctesting", @@ -86,9 +88,13 @@ jobs: os: windows-latest tox_env: "py310-xdist" - name: "windows-py311" - python: "3.11-dev" + python: "3.11" os: windows-latest tox_env: "py311" + - name: "windows-py312" + python: "3.12-dev" + os: windows-latest + tox_env: "py312" - name: "ubuntu-py37" python: "3.7" @@ -116,10 +122,15 @@ jobs: os: ubuntu-latest tox_env: "py310-xdist" - name: "ubuntu-py311" - python: "3.11-dev" + python: "3.11" os: ubuntu-latest tox_env: "py311" use_coverage: true + - name: "ubuntu-py312" + python: "3.12-dev" + os: ubuntu-latest + tox_env: "py312" + use_coverage: true - name: "ubuntu-pypy3" python: "pypy-3.7" os: ubuntu-latest @@ -129,19 +140,19 @@ jobs: python: "3.7" os: macos-latest tox_env: "py37-xdist" - - name: "macos-py38" - python: "3.8" - os: macos-latest - tox_env: "py38-xdist" - use_coverage: true - name: "macos-py39" python: "3.9" os: macos-latest tox_env: "py39-xdist" + use_coverage: true - name: "macos-py310" python: "3.10" os: macos-latest tox_env: "py310-xdist" + - name: "macos-py312" + python: "3.12-dev" + os: macos-latest + tox_env: "py312-xdist" - name: "plugins" python: "3.9" From 7d5207a7369f9560c75ee90e070727f34e04f1ce Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 23 May 2023 15:13:55 +0300 Subject: [PATCH 098/157] Declare support for Python 3.12 --- .pre-commit-config.yaml | 2 +- changelog/10894.bugfix.rst | 1 + setup.cfg | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/10894.bugfix.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ecaee56ced..0edb859ddf3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -50,7 +50,7 @@ repos: rev: v2.3.0 hooks: - id: setup-cfg-fmt - args: ["--max-py-version=3.11", "--include-version-classifiers"] + args: ["--max-py-version=3.12", "--include-version-classifiers"] - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: diff --git a/changelog/10894.bugfix.rst b/changelog/10894.bugfix.rst new file mode 100644 index 00000000000..66c6cd73f3c --- /dev/null +++ b/changelog/10894.bugfix.rst @@ -0,0 +1 @@ +Support for Python 3.12 (beta at the time of writing). diff --git a/setup.cfg b/setup.cfg index 2eee4cf5311..bc93b1c06b9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,6 +22,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Topic :: Software Development :: Libraries Topic :: Software Development :: Testing Topic :: Utilities From 40590008349facb37d48ec147c0d3b6d663cfc4c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 26 May 2023 20:28:21 +0300 Subject: [PATCH 099/157] testing/python/collect: replace use of deprecated/removed `imp` module --- testing/python/collect.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/testing/python/collect.py b/testing/python/collect.py index 41845517bf0..de10ce4083a 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -897,25 +897,29 @@ def pytest_pycollect_makeitem(collector, name, obj): def test_issue2369_collect_module_fileext(self, pytester: Pytester) -> None: """Ensure we can collect files with weird file extensions as Python modules (#2369)""" - # We'll implement a little finder and loader to import files containing + # Implement a little meta path finder to import files containing # Python source code whose file extension is ".narf". pytester.makeconftest( """ - import sys, os, imp + import sys + import os.path + from importlib.util import spec_from_loader + from importlib.machinery import SourceFileLoader from _pytest.python import Module - class Loader(object): - def load_module(self, name): - return imp.load_source(name, name + ".narf") - class Finder(object): - def find_module(self, name, path=None): - if os.path.exists(name + ".narf"): - return Loader() - sys.meta_path.append(Finder()) + class MetaPathFinder: + def find_spec(self, fullname, path, target=None): + if os.path.exists(fullname + ".narf"): + return spec_from_loader( + fullname, + SourceFileLoader(fullname, fullname + ".narf"), + ) + sys.meta_path.append(MetaPathFinder()) def pytest_collect_file(file_path, parent): if file_path.suffix == ".narf": - return Module.from_parent(path=file_path, parent=parent)""" + return Module.from_parent(path=file_path, parent=parent) + """ ) pytester.makefile( ".narf", From 6b3ece5bdb1c013f62db55004a42b7fb221d3fd1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 9 Jun 2023 11:28:10 +0300 Subject: [PATCH 100/157] ci; use check-latest: true for -dev pythons When testing -dev python versions, we want to always use the latest. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5435949fced..cf5027223e1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -179,6 +179,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} + check-latest: ${{ endsWith(matrix.python, '-dev') }} - name: Install dependencies run: | From 0142bb6687bf40e8928fb0a46eee4a794198f1cb Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 10 Jun 2023 22:30:12 +0300 Subject: [PATCH 101/157] Merge pull request #11096 from pytest-dev/release-7.3.2 Prepare release 7.3.2 (cherry picked from commit 5dcd2be4661bc606b3399bff3614c0691ce9c13f) --- changelog/10169.bugfix.rst | 1 - changelog/10894.bugfix.rst | 1 - changelog/10987.bugfix.rst | 1 - changelog/10999.bugfix.rst | 1 - changelog/11028.bugfix.rst | 1 - changelog/11054.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.3.2.rst | 21 +++++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 24 ++++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- 11 files changed, 48 insertions(+), 8 deletions(-) delete mode 100644 changelog/10169.bugfix.rst delete mode 100644 changelog/10894.bugfix.rst delete mode 100644 changelog/10987.bugfix.rst delete mode 100644 changelog/10999.bugfix.rst delete mode 100644 changelog/11028.bugfix.rst delete mode 100644 changelog/11054.bugfix.rst create mode 100644 doc/en/announce/release-7.3.2.rst diff --git a/changelog/10169.bugfix.rst b/changelog/10169.bugfix.rst deleted file mode 100644 index cbf3516a93d..00000000000 --- a/changelog/10169.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug where very long option names could cause pytest to break with ``OSError: [Errno 36] File name too long`` on some systems. diff --git a/changelog/10894.bugfix.rst b/changelog/10894.bugfix.rst deleted file mode 100644 index 66c6cd73f3c..00000000000 --- a/changelog/10894.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Support for Python 3.12 (beta at the time of writing). diff --git a/changelog/10987.bugfix.rst b/changelog/10987.bugfix.rst deleted file mode 100644 index 2aafff5f512..00000000000 --- a/changelog/10987.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -:confval:`testpaths` is now honored to load root ``conftests``. diff --git a/changelog/10999.bugfix.rst b/changelog/10999.bugfix.rst deleted file mode 100644 index 08c68da01bf..00000000000 --- a/changelog/10999.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -The `monkeypatch` `setitem`/`delitem` type annotations now allow `TypedDict` arguments. diff --git a/changelog/11028.bugfix.rst b/changelog/11028.bugfix.rst deleted file mode 100644 index 9efc04ba69f..00000000000 --- a/changelog/11028.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug in assertion rewriting where a variable assigned with the walrus operator could not be used later in a function call. diff --git a/changelog/11054.bugfix.rst b/changelog/11054.bugfix.rst deleted file mode 100644 index a8ee04fe304..00000000000 --- a/changelog/11054.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``--last-failed``'s "(skipped N files)" functionality for files inside of packages (directories with `__init__.py` files). diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index e3919f88ea6..bcc0669a62f 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.3.2 release-7.3.1 release-7.3.0 release-7.2.2 diff --git a/doc/en/announce/release-7.3.2.rst b/doc/en/announce/release-7.3.2.rst new file mode 100644 index 00000000000..b3b112f0d8e --- /dev/null +++ b/doc/en/announce/release-7.3.2.rst @@ -0,0 +1,21 @@ +pytest-7.3.2 +======================================= + +pytest 7.3.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Adam J. Stewart +* Alessio Izzo +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 7e9b51d002d..7ae185f6c7d 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -207,7 +207,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:29 + monkeypatch -- .../_pytest/monkeypatch.py:30 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 7d6eb1ffacc..cdc9e66f68b 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,30 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.3.2 (2023-06-10) +========================= + +Bug Fixes +--------- + +- `#10169 `_: Fix bug where very long option names could cause pytest to break with ``OSError: [Errno 36] File name too long`` on some systems. + + +- `#10894 `_: Support for Python 3.12 (beta at the time of writing). + + +- `#10987 `_: :confval:`testpaths` is now honored to load root ``conftests``. + + +- `#10999 `_: The `monkeypatch` `setitem`/`delitem` type annotations now allow `TypedDict` arguments. + + +- `#11028 `_: Fixed bug in assertion rewriting where a variable assigned with the walrus operator could not be used later in a function call. + + +- `#11054 `_: Fixed ``--last-failed``'s "(skipped N files)" functionality for files inside of packages (directories with `__init__.py` files). + + pytest 7.3.1 (2023-04-14) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index f4157114153..2dbf7d3870c 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 7.3.1 + pytest 7.3.2 .. _`simpletest`: From 8174a301642da3cecd828c82cdc8279ab9511b8a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 10 Jun 2023 22:34:59 +0300 Subject: [PATCH 102/157] changelog: add note to `norecursedir`/`pytest_ignore_collect` change (#11095) --- changelog/11081.improvement.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/changelog/11081.improvement.rst b/changelog/11081.improvement.rst index 227e478d4bc..ccfaf6016ae 100644 --- a/changelog/11081.improvement.rst +++ b/changelog/11081.improvement.rst @@ -1 +1,7 @@ The :confval:`norecursedir` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. + +If after updating to this version you see that your `norecursedir` setting is not being respected, +it means that a conftest or a plugin you use has a bad `pytest_ignore_collect` implementation. +Most likely, your hook returns `False` for paths it does not want to ignore, +which ends the processing and doesn't allow other plugins, including pytest itself, to ignore the path. +The fix is to return `None` instead of `False` for paths your hook doesn't want to ignore. From 2d824329ebf5455aaf4c6f8aa29afff401abe315 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 04:19:01 +0000 Subject: [PATCH 103/157] build(deps): Bump django in /testing/plugins_integration (#11102) Bumps [django](https://github.com/django/django) from 4.2.1 to 4.2.2. - [Commits](https://github.com/django/django/compare/4.2.1...4.2.2) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 7db8cc0abdb..f9ca76547c8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.7.0 -django==4.2.1 +django==4.2.2 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 pytest-cov==4.1.0 From b7a142f4babddce76168e9cb00bf5de6b145c0e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 05:36:28 +0000 Subject: [PATCH 104/157] [pre-commit.ci] pre-commit autoupdate (#11103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.4.0 → v3.6.0](https://github.com/asottile/pyupgrade/compare/v3.4.0...v3.6.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0edb859ddf3..ebf9f9f5787 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py37-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.4.0 + rev: v3.6.0 hooks: - id: pyupgrade args: [--py37-plus] From b55c02c3c9914a48e00fe8ab1cd7d903ab3b08c0 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 15 Jun 2023 14:17:14 +0200 Subject: [PATCH 105/157] doc: Add ep2023 training (#11113) --- doc/en/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/index.rst b/doc/en/index.rst index 87213878890..de07831ac14 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,6 +2,7 @@ .. sidebar:: Next Open Trainings + - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, July 18th (3h), Prague/Remote - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Leipzig/Remote Also see :doc:`previous talks and blogposts `. From fa09f6dcc60ba350771d10027061c135a2bdb66d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 18 Jun 2023 09:40:52 -0300 Subject: [PATCH 106/157] [automated] Update plugin list (#11117) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 270 ++++++++++++++++++------------- 1 file changed, 159 insertions(+), 111 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 40f9b5baed7..c882130b03e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -13,7 +13,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1261 plugins. +This list contains 1267 plugins. .. only:: not latex @@ -118,6 +118,7 @@ This list contains 1261 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A + :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jun 09, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A @@ -174,7 +175,7 @@ This list contains 1261 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Feb 13, 2023 5 - Production/Stable pytest + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jun 06, 2023 N/A pytest :pypi:`pytest-checkdocs` check the README when running tests Oct 09, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -231,7 +232,7 @@ This list contains 1261 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 02, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 14, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -271,7 +272,7 @@ This list contains 1261 plugins. :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) - :pypi:`pytest-dbt` Unit test dbt models with standard python tooling May 31, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. May 03, 2023 N/A pytest (>=6.2.5) ; extra == 'test' @@ -342,7 +343,7 @@ This list contains 1261 plugins. :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Sep 26, 2022 3 - Alpha pytest (>=4.6) + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Jun 08, 2023 3 - Alpha pytest (>=4.6) :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) @@ -355,7 +356,7 @@ This list contains 1261 plugins. :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A :pypi:`pytest-easy-api` Simple API testing with pytest Mar 26, 2018 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A @@ -370,13 +371,13 @@ This list contains 1261 plugins. :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` pytest embedded plugin Jun 06, 2023 N/A pytest (>=7.0) - :pypi:`pytest-embedded-arduino` pytest embedded plugin for Arduino projects Jun 06, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` pytest embedded plugin for esp-idf project Jun 06, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` pytest embedded plugin for testing with jtag Jun 06, 2023 N/A N/A - :pypi:`pytest-embedded-qemu` pytest embedded plugin for qemu, not target chip Jun 06, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` pytest embedded plugin for testing serial ports Jun 06, 2023 N/A N/A - :pypi:`pytest-embedded-serial-esp` pytest embedded plugin for testing espressif boards via serial ports Jun 06, 2023 N/A N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jun 14, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jun 14, 2023 5 - Production/Stable N/A :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) @@ -385,7 +386,7 @@ This list contains 1261 plugins. :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A :pypi:`pytest-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A - :pypi:`pytest-env` py.test plugin that allows you to add environment variables. Oct 23, 2022 5 - Production/Stable pytest>=7.1.3 + :pypi:`pytest-env` py.test plugin that allows you to add environment variables. Jun 15, 2023 5 - Production/Stable pytest>=7.3.1 :pypi:`pytest-envfiles` A py.test plugin that parses environment files before running tests Oct 08, 2015 3 - Alpha N/A :pypi:`pytest-env-info` Push information about the running pytest into envvars Nov 25, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-envraw` py.test plugin that allows you to add environment variables. Aug 27, 2020 4 - Beta pytest (>=2.6.0) @@ -431,7 +432,7 @@ This list contains 1261 plugins. :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest - :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Mar 05, 2020 N/A N/A + :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Jun 15, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) @@ -456,7 +457,7 @@ This list contains 1261 plugins. :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Mar 18, 2022 4 - Beta pytest (>=7.0) - :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. May 11, 2022 5 - Production/Stable pytest + :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jun 16, 2023 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) @@ -475,7 +476,7 @@ This list contains 1261 plugins. :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Oct 20, 2022 N/A pytest>=3.6 + :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 17, 2023 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) @@ -490,7 +491,7 @@ This list contains 1261 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 31, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 14, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -522,10 +523,10 @@ This list contains 1261 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 06, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 16, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A - :pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A + :pypi:`pytest-hot-reloading` Jun 16, 2023 N/A N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) @@ -583,7 +584,7 @@ This list contains 1261 plugins. :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-is-running` pytest plugin providing a function to check if pytest is running. Aug 19, 2022 5 - Production/Stable N/A + :pypi:`pytest-is-running` pytest plugin providing a function to check if pytest is running. Jun 16, 2023 5 - Production/Stable N/A :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -591,9 +592,9 @@ This list contains 1261 plugins. :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 07, 2022 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Dec 01, 2022 N/A pytest (~=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY May 29, 2023 4 - Beta pytest + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 14, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jun 06, 2023 4 - Beta pytest :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -604,7 +605,7 @@ This list contains 1261 plugins. :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 30, 2023 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest - :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Oct 01, 2022 N/A pytest + :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest @@ -643,7 +644,7 @@ This list contains 1261 plugins. :pypi:`pytest-local-badge` Generate local badges (shields) reporting your test suite status. Jan 15, 2023 N/A pytest (>=6.1.0) :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 04, 2022 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jan 30, 2023 4 - Beta N/A - :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Oct 17, 2022 4 - Beta pytest (>=6.0.0,<7.0.0) + :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jul 20, 2022 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) @@ -686,20 +687,20 @@ This list contains 1261 plugins. :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin May 25, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Jun 08, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 05, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Jun 15, 2023 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 23, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jun 09, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -741,7 +742,7 @@ This list contains 1261 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Mar 06, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 07, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -803,7 +804,7 @@ This list contains 1261 plugins. :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-persistence` Pytest tool for persistent objects May 16, 2023 N/A N/A + :pypi:`pytest-persistence` Pytest tool for persistent objects Jun 14, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) @@ -846,7 +847,7 @@ This list contains 1261 plugins. :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Dec 28, 2021 5 - Production/Stable pytest (>=6) + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 16, 2023 5 - Production/Stable pytest>=7.3.2 :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A @@ -867,7 +868,7 @@ This list contains 1261 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 02, 2023 N/A pytest + :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 11, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) @@ -885,14 +886,14 @@ This list contains 1261 plugins. :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins May 31, 2023 5 - Production/Stable pytest (>=6.2.5) + :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 09, 2023 5 - Production/Stable pytest (>=6.2.5) :pypi:`pytest-qml` Run QML Tests with pytest Dec 02, 2020 4 - Beta pytest (>=6.0.0) :pypi:`pytest-qr` pytest plugin to generate test result QR codes Nov 25, 2021 4 - Beta N/A :pypi:`pytest-qt` pytest support for PyQt and PySide applications Oct 25, 2022 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) - :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Feb 11, 2022 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jun 16, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) @@ -938,7 +939,8 @@ This list contains 1261 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal May 24, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 08, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -956,7 +958,7 @@ This list contains 1261 plugins. :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed May 11, 2022 5 - Production/Stable pytest + :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jun 16, 2023 5 - Production/Stable pytest :pypi:`pytest-result-log` Write the execution result of the case to the log Apr 17, 2023 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) @@ -964,7 +966,7 @@ This list contains 1261 plugins. :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-reverse` Pytest plugin to reverse test order. May 11, 2022 5 - Production/Stable pytest + :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jun 16, 2023 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) :pypi:`pytest-richtrace` Nov 05, 2022 N/A pytest (>=7.2.0,<8.0.0) @@ -978,13 +980,14 @@ This list contains 1261 plugins. :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Apr 28, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jun 08, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 + :pypi:`pytest-runtime-yoyo` run case mark timeout Jun 12, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-ry-demo1` 测试 Mar 26, 2023 N/A N/A :pypi:`pytest-saccharin` pytest-saccharin is a updated fork of pytest-sugar, a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Oct 31, 2022 3 - Alpha N/A :pypi:`pytest-salt` Pytest Salt Plugin Jan 27, 2020 4 - Beta N/A @@ -995,14 +998,14 @@ This list contains 1261 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 02, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 02, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1130,7 +1133,7 @@ This list contains 1261 plugins. :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods May 18, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods Jun 16, 2023 4 - Beta N/A :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-oc` nOly selects tests affected by changed files and methods Jun 01, 2022 4 - Beta pytest (<8,>=5) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5) @@ -1157,6 +1160,7 @@ This list contains 1261 plugins. :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-time` Jun 16, 2023 3 - Alpha pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Jan 18, 2022 5 - Production/Stable pytest (>=5.0.0) :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A @@ -1193,13 +1197,13 @@ This list contains 1261 plugins. :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Apr 06, 2023 4 - Beta N/A + :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Jun 12, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-typhoon-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A - :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Nov 04, 2022 4 - Beta N/A + :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Jun 10, 2023 4 - Beta N/A :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1211,6 +1215,7 @@ This list contains 1261 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1237,7 +1242,7 @@ This list contains 1261 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` May 11, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 03, 2023 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 11, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest @@ -1254,6 +1259,7 @@ This list contains 1261 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A @@ -1269,7 +1275,7 @@ This list contains 1261 plugins. :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml May 28, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml May 30, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 08, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A @@ -1972,6 +1978,13 @@ This list contains 1261 plugins. Fixtures for testing Google Appengine (GAE) apps + :pypi:`pytest-beeprint` + *last release*: Jun 09, 2023, + *status*: 4 - Beta, + *requires*: N/A + + use icdiff for better error messages in pytest assertions + :pypi:`pytest-bench` *last release*: Jul 21, 2014, *status*: 3 - Alpha, @@ -2365,8 +2378,8 @@ This list contains 1261 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Feb 13, 2023, - *status*: 5 - Production/Stable, + *last release*: Jun 06, 2023, + *status*: N/A, *requires*: pytest A pytest plugin that allows multiple failures per test. @@ -2764,7 +2777,7 @@ This list contains 1261 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Jun 02, 2023, + *last release*: Jun 14, 2023, *status*: N/A, *requires*: N/A @@ -3044,7 +3057,7 @@ This list contains 1261 plugins. :pypi:`pytest-dbt` - *last release*: May 31, 2023, + *last release*: Jun 08, 2023, *status*: 2 - Pre-Alpha, *requires*: pytest (>=7.0.0,<8.0.0) @@ -3541,7 +3554,7 @@ This list contains 1261 plugins. A simple pytest plugin to import names and add them to the doctest namespace. :pypi:`pytest-doctestplus` - *last release*: Sep 26, 2022, + *last release*: Jun 08, 2023, *status*: 3 - Alpha, *requires*: pytest (>=4.6) @@ -3632,7 +3645,7 @@ This list contains 1261 plugins. A pytest plugin to rerun tests dynamically based off of test outcome and output. :pypi:`pytest-dynamodb` - *last release*: Mar 27, 2023, + *last release*: Jun 12, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -3737,53 +3750,53 @@ This list contains 1261 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jun 06, 2023, - *status*: N/A, - *requires*: pytest (>=7.0) + *last release*: Jun 14, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.0 - pytest embedded plugin + A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jun 06, 2023, + *last release*: Jun 14, 2023, *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for Arduino projects + Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jun 06, 2023, + *last release*: Jun 14, 2023, *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for esp-idf project + Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jun 06, 2023, - *status*: N/A, + *last release*: Jun 14, 2023, + *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for testing with jtag + Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jun 06, 2023, + *last release*: Jun 14, 2023, *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for qemu, not target chip + Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jun 06, 2023, - *status*: N/A, + *last release*: Jun 14, 2023, + *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for testing serial ports + Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jun 06, 2023, - *status*: N/A, + *last release*: Jun 14, 2023, + *status*: 5 - Production/Stable, *requires*: N/A - pytest embedded plugin for testing espressif boards via serial ports + Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embrace` *last release*: Mar 25, 2023, @@ -3842,9 +3855,9 @@ This list contains 1261 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Oct 23, 2022, + *last release*: Jun 15, 2023, *status*: 5 - Production/Stable, - *requires*: pytest>=7.1.3 + *requires*: pytest>=7.3.1 py.test plugin that allows you to add environment variables. @@ -4164,9 +4177,9 @@ This list contains 1261 plugins. A fixture which allows easy replacement of fastapi dependencies for testing :pypi:`pytest-fastest` - *last release*: Mar 05, 2020, - *status*: N/A, - *requires*: N/A + *last release*: Jun 15, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=4.4) Use SCM and coverage to run only needed tests @@ -4339,7 +4352,7 @@ This list contains 1261 plugins. pytest plugin to check FLAKE8 requirements :pypi:`pytest-flake8-path` - *last release*: May 11, 2022, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -4472,7 +4485,7 @@ This list contains 1261 plugins. Wrap tests with fixtures in freeze_time :pypi:`pytest-freezer` - *last release*: Oct 20, 2022, + *last release*: Jun 17, 2023, *status*: N/A, *requires*: pytest>=3.6 @@ -4577,7 +4590,7 @@ This list contains 1261 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: May 31, 2023, + *last release*: Jun 14, 2023, *status*: N/A, *requires*: N/A @@ -4801,7 +4814,7 @@ This list contains 1261 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 06, 2023, + *last release*: Jun 16, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -4822,7 +4835,7 @@ This list contains 1261 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: May 18, 2023, + *last release*: Jun 16, 2023, *status*: N/A, *requires*: N/A @@ -5228,7 +5241,7 @@ This list contains 1261 plugins. py.test plugin to check import ordering using isort :pypi:`pytest-is-running` - *last release*: Aug 19, 2022, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5284,21 +5297,21 @@ This list contains 1261 plugins. A plugin to generate customizable jinja-based HTML reports in pytest :pypi:`pytest-jira` - *last release*: Apr 07, 2022, + *last release*: Jun 12, 2023, *status*: 3 - Alpha, *requires*: N/A py.test JIRA integration plugin, using markers :pypi:`pytest-jira-xfail` - *last release*: Dec 01, 2022, + *last release*: Jun 14, 2023, *status*: N/A, - *requires*: pytest (~=7.2.0) + *requires*: pytest (>=7.2.0) Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: May 29, 2023, + *last release*: Jun 06, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5375,7 +5388,7 @@ This list contains 1261 plugins. A reusable JupyterHub pytest plugin :pypi:`pytest-kafka` - *last release*: Oct 01, 2022, + *last release*: Jun 14, 2023, *status*: N/A, *requires*: pytest @@ -5648,7 +5661,7 @@ This list contains 1261 plugins. pytest plugin to test server connections locally. :pypi:`pytest-localstack` - *last release*: Oct 17, 2022, + *last release*: Jun 07, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.0.0,<7.0.0) @@ -5949,7 +5962,7 @@ This list contains 1261 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: May 25, 2023, + *last release*: Jun 08, 2023, *status*: N/A, *requires*: pytest @@ -5998,7 +6011,7 @@ This list contains 1261 plugins. pytest plugin to display test execution output like a mochajs :pypi:`pytest-mock` - *last release*: Oct 05, 2022, + *last release*: Jun 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=5.0) @@ -6040,7 +6053,7 @@ This list contains 1261 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: May 23, 2023, + *last release*: Jun 09, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6334,7 +6347,7 @@ This list contains 1261 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Mar 06, 2023, + *last release*: Jun 07, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -6768,7 +6781,7 @@ This list contains 1261 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-persistence` - *last release*: May 16, 2023, + *last release*: Jun 14, 2023, *status*: N/A, *requires*: N/A @@ -7069,9 +7082,9 @@ This list contains 1261 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Dec 28, 2021, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6) + *requires*: pytest>=7.3.2 pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) @@ -7216,7 +7229,7 @@ This list contains 1261 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jun 02, 2023, + *last release*: Jun 11, 2023, *status*: N/A, *requires*: pytest @@ -7342,7 +7355,7 @@ This list contains 1261 plugins. Pytest plugin for uploading test results to your QA Touch Testrun. :pypi:`pytest-qgis` - *last release*: May 31, 2023, + *last release*: Jun 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2.5) @@ -7391,9 +7404,9 @@ This list contains 1261 plugins. pytest plugin to generate random data inspired by QuickCheck :pypi:`pytest-rabbitmq` - *last release*: Feb 11, 2022, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0) + *requires*: pytest (>=6.2) RabbitMQ process and client fixtures for pytest @@ -7713,12 +7726,19 @@ This list contains 1261 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: May 24, 2023, + *last release*: Jun 08, 2023, *status*: N/A, *requires*: pytest (>=3.8.0) Agent for Reporting results of tests to the Report Portal + :pypi:`pytest-reports` + *last release*: Jun 07, 2023, + *status*: N/A, + *requires*: N/A + + An interesting python package + :pypi:`pytest-reqs` *last release*: May 12, 2019, *status*: N/A, @@ -7839,7 +7859,7 @@ This list contains 1261 plugins. :pypi:`pytest-restrict` - *last release*: May 11, 2022, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7895,7 +7915,7 @@ This list contains 1261 plugins. :pypi:`pytest-reverse` - *last release*: May 11, 2022, + *last release*: Jun 16, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7993,7 +8013,7 @@ This list contains 1261 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Apr 28, 2023, + *last release*: Jun 08, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8041,6 +8061,13 @@ This list contains 1261 plugins. Call runtime_xfail() to mark running test as xfail. + :pypi:`pytest-runtime-yoyo` + *last release*: Jun 12, 2023, + *status*: N/A, + *requires*: pytest (>=7.2.0) + + run case mark timeout + :pypi:`pytest-ry-demo1` *last release*: Mar 26, 2023, *status*: N/A, @@ -8112,7 +8139,7 @@ This list contains 1261 plugins. :pypi:`pytest-sbase` - *last release*: Jun 02, 2023, + *last release*: Jun 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8161,7 +8188,7 @@ This list contains 1261 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jun 02, 2023, + *last release*: Jun 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9057,9 +9084,9 @@ This list contains 1261 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: May 18, 2023, + *last release*: Jun 16, 2023, *status*: 4 - Beta, - *requires*: pytest (<8,>=5) + *requires*: N/A selects tests affected by changed files and methods @@ -9245,6 +9272,13 @@ This list contains 1261 plugins. Ticking on tests + :pypi:`pytest-time` + *last release*: Jun 16, 2023, + *status*: 3 - Alpha, + *requires*: pytest + + + :pypi:`pytest-timeit` *last release*: Oct 13, 2016, *status*: 4 - Beta, @@ -9498,7 +9532,7 @@ This list contains 1261 plugins. Test Class Base :pypi:`pytest-tui` - *last release*: Apr 06, 2023, + *last release*: Jun 12, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9540,7 +9574,7 @@ This list contains 1261 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime :pypi:`pytest-typhoon-xray` - *last release*: Nov 04, 2022, + *last release*: Jun 10, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9623,6 +9657,13 @@ This list contains 1261 plugins. Set a test as unstable to return 0 even if it failed + :pypi:`pytest-unused-fixtures` + *last release*: Jun 15, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.3.2,<8.0.0) + + A pytest plugin to list unused fixtures after a test run. + :pypi:`pytest-upload-report` *last release*: Jun 18, 2021, *status*: 5 - Production/Stable, @@ -9806,7 +9847,7 @@ This list contains 1261 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Jun 03, 2023, + *last release*: Jun 11, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9924,6 +9965,13 @@ This list contains 1261 plugins. pytest plugin helps to reproduce failures for particular xdist node + :pypi:`pytest-xdist-worker-stats` + *last release*: Jun 15, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.3.2,<8.0.0) + + A pytest plugin to list worker statistics after a xdist run. + :pypi:`pytest-xfaillist` *last release*: Sep 17, 2021, *status*: N/A, @@ -10030,7 +10078,7 @@ This list contains 1261 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: May 30, 2023, + *last release*: Jun 08, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) From 1eb83706b6c7a4c2789719711ececaa0b8c5a9f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 04:15:50 +0000 Subject: [PATCH 107/157] build(deps): Bump pytest-mock in /testing/plugins_integration (#11119) Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.10.0 to 3.11.1. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.10.0...v3.11.1) --- updated-dependencies: - dependency-name: pytest-mock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index f9ca76547c8..d56720c0282 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -6,7 +6,7 @@ pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 pytest-html==3.2.0 -pytest-mock==3.10.0 +pytest-mock==3.11.1 pytest-rerunfailures==11.1.2 pytest-sugar==0.9.7 pytest-trio==0.7.0 From 8528052a9514b1d81103d9c0d4aad5792849a1b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 19:22:49 -0300 Subject: [PATCH 108/157] build(deps): Bump peter-evans/create-pull-request from 5.0.0 to 5.0.2 (#11120) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.0 to 5.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5...153407881ec5c347639a548ade7d8ad1d6740e38) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index ef92fef8836..e7cbc4e96be 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -38,7 +38,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 + uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 5b355183891962fe466b227ce15d1b34714b8eef Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Mon, 19 Jun 2023 20:06:21 -0700 Subject: [PATCH 109/157] Apply suggestions from code review Co-authored-by: Ronnie Dutta <61982285+MetRonnie@users.noreply.github.com> --- src/_pytest/logging.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 92a0cb6c639..ff16e0ff1a6 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -447,12 +447,9 @@ def clear(self) -> None: self.handler.reset() def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: - """Sets the threshold for this logger to level. + """Set the threshold level of a logger for the duration of a test. - Logging messages which are less severe than level will be ignored; logging messages - which have severity level or higher will be emitted by whichever handler or handlers - service this logger, unless a handler’s level has been set to a higher severity level - than `level`. + Logging messages which are less severe than this level will not be captured. .. versionchanged:: 3.4 The levels of the loggers changed by this function will be From 797b924fc44189d0b9c2ad905410f0bd89461ab7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 06:38:36 +0000 Subject: [PATCH 110/157] [pre-commit.ci] pre-commit autoupdate (#11124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/blacken-docs: 1.13.0 → 1.14.0](https://github.com/asottile/blacken-docs/compare/1.13.0...1.14.0) - [github.com/asottile/reorder-python-imports: v3.9.0 → v3.10.0](https://github.com/asottile/reorder-python-imports/compare/v3.9.0...v3.10.0) - [github.com/asottile/pyupgrade: v3.6.0 → v3.7.0](https://github.com/asottile/pyupgrade/compare/v3.6.0...v3.7.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ebf9f9f5787..b5089e12942 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: black args: [--safe, --quiet] - repo: https://github.com/asottile/blacken-docs - rev: 1.13.0 + rev: 1.14.0 hooks: - id: blacken-docs additional_dependencies: [black==23.1.0] @@ -37,12 +37,12 @@ repos: - flake8-typing-imports==1.12.0 - flake8-docstrings==1.5.0 - repo: https://github.com/asottile/reorder-python-imports - rev: v3.9.0 + rev: v3.10.0 hooks: - id: reorder-python-imports args: ['--application-directories=.:src', --py37-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.6.0 + rev: v3.7.0 hooks: - id: pyupgrade args: [--py37-plus] From a704605cf182e1142c1e9b1da4c7cad1a1749376 Mon Sep 17 00:00:00 2001 From: nondescryptid Date: Tue, 20 Jun 2023 04:55:39 -0700 Subject: [PATCH 111/157] Fix encoding warnings --- testing/acceptance_test.py | 10 ++-- testing/python/fixtures.py | 94 +++++++++++++++++++++++------------ testing/python/metafunc.py | 14 ++++-- testing/test_assertrewrite.py | 21 +++++--- testing/test_collection.py | 54 +++++++++++++------- testing/test_config.py | 31 ++++++++---- testing/test_conftest.py | 71 +++++++++++++++++--------- testing/test_doctest.py | 13 +++-- testing/test_monkeypatch.py | 12 +++-- testing/test_pathlib.py | 6 +-- tox.ini | 4 ++ 11 files changed, 218 insertions(+), 112 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 680afe13391..0046d05b8b2 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -267,7 +267,7 @@ def test_conftest_printing_shows_if_error(self, pytester: Pytester) -> None: def test_issue109_sibling_conftests_not_loaded(self, pytester: Pytester) -> None: sub1 = pytester.mkdir("sub1") sub2 = pytester.mkdir("sub2") - sub1.joinpath("conftest.py").write_text("assert 0") + sub1.joinpath("conftest.py").write_text("assert 0", encoding="utf-8") result = pytester.runpytest(sub2) assert result.ret == ExitCode.NO_TESTS_COLLECTED sub2.joinpath("__init__.py").touch() @@ -467,7 +467,7 @@ def test_plugins_given_as_strings( assert "invalid" in str(excinfo.value) p = pytester.path.joinpath("test_test_plugins_given_as_strings.py") - p.write_text("def test_foo(): pass") + p.write_text("def test_foo(): pass", encoding="utf-8") mod = types.ModuleType("myplugin") monkeypatch.setitem(sys.modules, "myplugin", mod) assert pytest.main(args=[str(pytester.path)], plugins=["myplugin"]) == 0 @@ -587,7 +587,7 @@ def pytest_addoption(self, parser): def test_pyargs_importerror(self, pytester: Pytester, monkeypatch) -> None: monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", False) path = pytester.mkpydir("tpkg") - path.joinpath("test_hello.py").write_text("raise ImportError") + path.joinpath("test_hello.py").write_text("raise ImportError", encoding="utf-8") result = pytester.runpytest("--pyargs", "tpkg.test_hello", syspathinsert=True) assert result.ret != 0 @@ -597,10 +597,10 @@ def test_pyargs_importerror(self, pytester: Pytester, monkeypatch) -> None: def test_pyargs_only_imported_once(self, pytester: Pytester) -> None: pkg = pytester.mkpydir("foo") pkg.joinpath("test_foo.py").write_text( - "print('hello from test_foo')\ndef test(): pass" + "print('hello from test_foo')\ndef test(): pass", encoding="utf-8" ) pkg.joinpath("conftest.py").write_text( - "def pytest_configure(config): print('configuring')" + "def pytest_configure(config): print('configuring')", encoding="utf-8" ) result = pytester.runpytest( diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index d996f80bb93..e62db8c2653 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -287,7 +287,8 @@ def spam(request): def spam(): return 'spam' """ - ) + ), + encoding="utf-8", ) testfile = subdir.joinpath("test_spam.py") testfile.write_text( @@ -296,7 +297,8 @@ def spam(): def test_spam(spam): assert spam == "spam" """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*1 passed*"]) @@ -359,7 +361,8 @@ def spam(): def spam(request): return request.param """ - ) + ), + encoding="utf-8", ) testfile = subdir.joinpath("test_spam.py") testfile.write_text( @@ -371,7 +374,8 @@ def test_spam(spam): assert spam == params['spam'] params['spam'] += 1 """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*3 passed*"]) @@ -403,7 +407,8 @@ def spam(): def spam(request): return request.param """ - ) + ), + encoding="utf-8", ) testfile = subdir.joinpath("test_spam.py") testfile.write_text( @@ -415,7 +420,8 @@ def test_spam(spam): assert spam == params['spam'] params['spam'] += 1 """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*3 passed*"]) @@ -1037,10 +1043,11 @@ def test_fixtures_sub_subdir_normalize_sep(self, pytester: Pytester) -> None: def arg1(): pass """ - ) + ), + encoding="utf-8", ) p = b.joinpath("test_module.py") - p.write_text("def test_func(arg1): pass") + p.write_text("def test_func(arg1): pass", encoding="utf-8") result = pytester.runpytest(p, "--fixtures") assert result.ret == 0 result.stdout.fnmatch_lines( @@ -1617,7 +1624,8 @@ def test_parsefactories_relative_node_ids( def one(): return 1 """ - ) + ), + encoding="utf-8", ) package.joinpath("test_x.py").write_text( textwrap.dedent( @@ -1625,7 +1633,8 @@ def one(): def test_x(one): assert one == 1 """ - ) + ), + encoding="utf-8", ) sub = package.joinpath("sub") sub.mkdir() @@ -1638,7 +1647,8 @@ def test_x(one): def one(): return 2 """ - ) + ), + encoding="utf-8", ) sub.joinpath("test_y.py").write_text( textwrap.dedent( @@ -1646,7 +1656,8 @@ def one(): def test_x(one): assert one == 2 """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=2) @@ -1671,7 +1682,8 @@ def setup_module(): def teardown_module(): values[:] = [] """ - ) + ), + encoding="utf-8", ) package.joinpath("test_x.py").write_text( textwrap.dedent( @@ -1680,7 +1692,8 @@ def teardown_module(): def test_x(): assert values == ["package"] """ - ) + ), + encoding="utf-8", ) package = pytester.mkdir("package2") package.joinpath("__init__.py").write_text( @@ -1692,7 +1705,8 @@ def setup_module(): def teardown_module(): values[:] = [] """ - ) + ), + encoding="utf-8", ) package.joinpath("test_x.py").write_text( textwrap.dedent( @@ -1701,7 +1715,8 @@ def teardown_module(): def test_x(): assert values == ["package2"] """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=2) @@ -1714,7 +1729,7 @@ def test_package_fixture_complex(self, pytester: Pytester) -> None: ) pytester.syspathinsert(pytester.path.name) package = pytester.mkdir("package") - package.joinpath("__init__.py").write_text("") + package.joinpath("__init__.py").write_text("", encoding="utf-8") package.joinpath("conftest.py").write_text( textwrap.dedent( """\ @@ -1731,7 +1746,8 @@ def two(): yield values values.pop() """ - ) + ), + encoding="utf-8", ) package.joinpath("test_x.py").write_text( textwrap.dedent( @@ -1742,7 +1758,8 @@ def test_package_autouse(): def test_package(one): assert values == ["package-auto", "package"] """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=2) @@ -1892,8 +1909,12 @@ def hello(): """ ) conftest.rename(a.joinpath(conftest.name)) - a.joinpath("test_something.py").write_text("def test_func(): pass") - b.joinpath("test_otherthing.py").write_text("def test_func(): pass") + a.joinpath("test_something.py").write_text( + "def test_func(): pass", encoding="utf-8" + ) + b.joinpath("test_otherthing.py").write_text( + "def test_func(): pass", encoding="utf-8" + ) result = pytester.runpytest() result.stdout.fnmatch_lines( """ @@ -1939,7 +1960,8 @@ def app(): import sys sys._myapp = "hello" """ - ) + ), + encoding="utf-8", ) sub = pkgdir.joinpath("tests") sub.mkdir() @@ -1952,7 +1974,8 @@ def app(): def test_app(): assert sys._myapp == "hello" """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run("-s") reprec.assertoutcome(passed=1) @@ -2882,7 +2905,7 @@ def test_fixture_finalizer(self, pytester: Pytester) -> None: def browser(request): def finalize(): - sys.stdout.write_text('Finalized') + sys.stdout.write_text('Finalized', encoding='utf-8') request.addfinalizer(finalize) return {} """ @@ -2900,7 +2923,8 @@ def browser(browser): def test_browser(browser): assert browser['visited'] is True """ - ) + ), + encoding="utf-8", ) reprec = pytester.runpytest("-s") for test in ["test_browser"]: @@ -3855,7 +3879,8 @@ def test_non_relative_path(self, pytester: Pytester) -> None: def fix_with_param(request): return request.param """ - ) + ), + encoding="utf-8", ) testfile = tests_dir.joinpath("test_foos.py") @@ -3867,7 +3892,8 @@ def fix_with_param(request): def test_foo(request): request.getfixturevalue('fix_with_param') """ - ) + ), + encoding="utf-8", ) os.chdir(tests_dir) @@ -4196,7 +4222,7 @@ def test_multiple_packages(self, pytester: Pytester) -> None: └── test_2.py """ root = pytester.mkdir("root") - root.joinpath("__init__.py").write_text("values = []") + root.joinpath("__init__.py").write_text("values = []", encoding="utf-8") sub1 = root.joinpath("sub1") sub1.mkdir() sub1.joinpath("__init__.py").touch() @@ -4211,7 +4237,8 @@ def fix(): yield values assert values.pop() == "pre-sub1" """ - ) + ), + encoding="utf-8", ) sub1.joinpath("test_1.py").write_text( textwrap.dedent( @@ -4220,7 +4247,8 @@ def fix(): def test_1(fix): assert values == ["pre-sub1"] """ - ) + ), + encoding="utf-8", ) sub2 = root.joinpath("sub2") sub2.mkdir() @@ -4236,7 +4264,8 @@ def fix(): yield values assert values.pop() == "pre-sub2" """ - ) + ), + encoding="utf-8", ) sub2.joinpath("test_2.py").write_text( textwrap.dedent( @@ -4245,7 +4274,8 @@ def fix(): def test_2(fix): assert values == ["pre-sub2"] """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=2) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index c1cc9c3d3bb..a9e9b526934 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1443,7 +1443,8 @@ def test_generate_tests_only_done_in_subdir(self, pytester: Pytester) -> None: def pytest_generate_tests(metafunc): assert metafunc.function.__name__ == "test_1" """ - ) + ), + encoding="utf-8", ) sub2.joinpath("conftest.py").write_text( textwrap.dedent( @@ -1451,10 +1452,15 @@ def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc): assert metafunc.function.__name__ == "test_2" """ - ) + ), + encoding="utf-8", + ) + sub1.joinpath("test_in_sub1.py").write_text( + "def test_1(): pass", encoding="utf-8" + ) + sub2.joinpath("test_in_sub2.py").write_text( + "def test_2(): pass", encoding="utf-8" ) - sub1.joinpath("test_in_sub1.py").write_text("def test_1(): pass") - sub2.joinpath("test_in_sub2.py").write_text("def test_2(): pass") result = pytester.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1) result.assert_outcomes(passed=3) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 245241af2b2..057b609ac7e 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -160,7 +160,8 @@ def test_rewrites_plugin_as_a_package(self, pytester: Pytester) -> None: "def special_asserter():\n" " def special_assert(x, y):\n" " assert x == y\n" - " return special_assert\n" + " return special_assert\n", + encoding="utf-8", ) pytester.makeconftest('pytest_plugins = ["plugin"]') pytester.makepyfile("def test(special_asserter): special_asserter(1, 2)\n") @@ -173,7 +174,9 @@ def test_honors_pep_235(self, pytester: Pytester, monkeypatch) -> None: pytester.makepyfile(test_y="x = 1") xdir = pytester.mkdir("x") pytester.mkpydir(str(xdir.joinpath("test_Y"))) - xdir.joinpath("test_Y").joinpath("__init__.py").write_text("x = 2") + xdir.joinpath("test_Y").joinpath("__init__.py").write_text( + "x = 2", encoding="utf-8" + ) pytester.makepyfile( "import test_y\n" "import test_Y\n" @@ -726,7 +729,7 @@ def __repr__(self): class TestRewriteOnImport: def test_pycache_is_a_file(self, pytester: Pytester) -> None: - pytester.path.joinpath("__pycache__").write_text("Hello") + pytester.path.joinpath("__pycache__").write_text("Hello", encoding="utf-8") pytester.makepyfile( """ def test_rewritten(): @@ -903,7 +906,8 @@ def test_package(self, pytester: Pytester) -> None: pkg.joinpath("test_blah.py").write_text( """ def test_rewritten(): - assert "@py_builtins" in globals()""" + assert "@py_builtins" in globals()""", + encoding="utf-8", ) assert pytester.runpytest().ret == 0 @@ -1066,7 +1070,7 @@ def test_read_pyc(self, tmp_path: Path) -> None: source = tmp_path / "source.py" pyc = Path(str(source) + "c") - source.write_text("def test(): pass") + source.write_text("def test(): pass", encoding="utf-8") py_compile.compile(str(source), str(pyc)) contents = pyc.read_bytes() @@ -1092,7 +1096,7 @@ def test_read_pyc_success(self, tmp_path: Path, pytester: Pytester) -> None: fn = tmp_path / "source.py" pyc = Path(str(fn) + "c") - fn.write_text("def test(): assert True") + fn.write_text("def test(): assert True", encoding="utf-8") source_stat, co = _rewrite_test(fn, config) _write_pyc(state, co, source_stat, pyc) @@ -1187,9 +1191,10 @@ def test_foo(self): data = pkgutil.get_data('foo.test_foo', 'data.txt') assert data == b'Hey' """ - ) + ), + encoding="utf-8", ) - path.joinpath("data.txt").write_text("Hey") + path.joinpath("data.txt").write_text("Hey", encoding="utf-8") result = pytester.runpytest() result.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/test_collection.py b/testing/test_collection.py index 3021398720f..3e1a044433b 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -140,7 +140,7 @@ def test_ignored_certain_directories(self, pytester: Pytester) -> None: ensure_file(tmp_path / ".bzr" / "test_notfound.py") ensure_file(tmp_path / "normal" / "test_found.py") for x in tmp_path.rglob("test_*.py"): - x.write_text("def test_hello(): pass", "utf-8") + x.write_text("def test_hello(): pass", encoding="utf-8") result = pytester.runpytest("--collect-only") s = result.stdout.str() @@ -162,7 +162,7 @@ def test_ignored_virtualenvs(self, pytester: Pytester, fname: str) -> None: bindir = "Scripts" if sys.platform.startswith("win") else "bin" ensure_file(pytester.path / "virtual" / bindir / fname) testfile = ensure_file(pytester.path / "virtual" / "test_invenv.py") - testfile.write_text("def test_hello(): pass") + testfile.write_text("def test_hello(): pass", encoding="utf-8") # by default, ignore tests inside a virtualenv result = pytester.runpytest() @@ -192,7 +192,7 @@ def test_ignored_virtualenvs_norecursedirs_precedence( # norecursedirs takes priority ensure_file(pytester.path / ".virtual" / bindir / fname) testfile = ensure_file(pytester.path / ".virtual" / "test_invenv.py") - testfile.write_text("def test_hello(): pass") + testfile.write_text("def test_hello(): pass", encoding="utf-8") result = pytester.runpytest("--collect-in-virtualenv") result.stdout.no_fnmatch_line("*test_invenv*") # ...unless the virtualenv is explicitly given on the CLI @@ -231,10 +231,14 @@ def test_custom_norecursedirs(self, pytester: Pytester) -> None: ) tmp_path = pytester.path ensure_file(tmp_path / "mydir" / "test_hello.py").write_text( - "def test_1(): pass" + "def test_1(): pass", encoding="utf-8" + ) + ensure_file(tmp_path / "xyz123" / "test_2.py").write_text( + "def test_2(): 0/0", encoding="utf-8" + ) + ensure_file(tmp_path / "xy" / "test_ok.py").write_text( + "def test_3(): pass", encoding="utf-8" ) - ensure_file(tmp_path / "xyz123" / "test_2.py").write_text("def test_2(): 0/0") - ensure_file(tmp_path / "xy" / "test_ok.py").write_text("def test_3(): pass") rec = pytester.inline_run() rec.assertoutcome(passed=1) rec = pytester.inline_run("xyz123/test_2.py") @@ -248,12 +252,14 @@ def test_testpaths_ini(self, pytester: Pytester, monkeypatch: MonkeyPatch) -> No """ ) tmp_path = pytester.path - ensure_file(tmp_path / "a" / "test_1.py").write_text("def test_a(): pass") + ensure_file(tmp_path / "a" / "test_1.py").write_text( + "def test_a(): pass", encoding="utf-8" + ) ensure_file(tmp_path / "b" / "tests" / "test_2.py").write_text( - "def test_b(): pass" + "def test_b(): pass", encoding="utf-8" ) ensure_file(tmp_path / "c" / "tests" / "test_3.py").write_text( - "def test_c(): pass" + "def test_c(): pass", encoding="utf-8" ) # executing from rootdir only tests from `testpaths` directories @@ -349,8 +355,8 @@ def pytest_ignore_collect(collection_path, config): """ ) sub = pytester.mkdir("xy123") - ensure_file(sub / "test_hello.py").write_text("syntax error") - sub.joinpath("conftest.py").write_text("syntax error") + ensure_file(sub / "test_hello.py").write_text("syntax error", encoding="utf-8") + sub.joinpath("conftest.py").write_text("syntax error", encoding="utf-8") pytester.makepyfile("def test_hello(): pass") pytester.makepyfile(test_one="syntax error") result = pytester.runpytest("--fulltrace") @@ -1060,13 +1066,18 @@ def test_fixture_scope_sibling_conftests(pytester: Pytester) -> None: def fix(): return 1 """ - ) + ), + encoding="utf-8", + ) + foo_path.joinpath("test_foo.py").write_text( + "def test_foo(fix): assert fix == 1", encoding="utf-8" ) - foo_path.joinpath("test_foo.py").write_text("def test_foo(fix): assert fix == 1") # Tests in `food/` should not see the conftest fixture from `foo/` food_path = pytester.mkpydir("food") - food_path.joinpath("test_food.py").write_text("def test_food(fix): assert fix == 1") + food_path.joinpath("test_food.py").write_text( + "def test_food(fix): assert fix == 1", encoding="utf-8" + ) res = pytester.runpytest() assert res.ret == 1 @@ -1197,7 +1208,8 @@ def test_collect_with_chdir_during_import(pytester: Pytester) -> None: os.chdir(%r) """ % (str(subdir),) - ) + ), + encoding="utf-8", ) pytester.makepyfile( """ @@ -1227,8 +1239,12 @@ def test_collect_pyargs_with_testpaths( ) -> None: testmod = pytester.mkdir("testmod") # NOTE: __init__.py is not collected since it does not match python_files. - testmod.joinpath("__init__.py").write_text("def test_func(): pass") - testmod.joinpath("test_file.py").write_text("def test_func(): pass") + testmod.joinpath("__init__.py").write_text( + "def test_func(): pass", encoding="utf-8" + ) + testmod.joinpath("test_file.py").write_text( + "def test_func(): pass", encoding="utf-8" + ) root = pytester.mkdir("root") root.joinpath("pytest.ini").write_text( @@ -1238,7 +1254,8 @@ def test_collect_pyargs_with_testpaths( addopts = --pyargs testpaths = testmod """ - ) + ), + encoding="utf-8", ) monkeypatch.setenv("PYTHONPATH", str(pytester.path), prepend=os.pathsep) with monkeypatch.context() as mp: @@ -1323,6 +1340,7 @@ def test_nodeid(request): assert request.node.nodeid == "test_real.py::test_nodeid" """ ), + encoding="utf-8", ) out_of_tree = pytester.mkdir("out_of_tree") diff --git a/testing/test_config.py b/testing/test_config.py index cdeb67aceff..3aec5d7631f 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -87,7 +87,8 @@ def test_append_parse_args( [pytest] addopts = --verbose """ - ) + ), + encoding="utf-8", ) config = pytester.parseconfig(tmp_path) assert config.option.color == "no" @@ -127,7 +128,8 @@ def test_ini_names(self, pytester: Pytester, name, section) -> None: """.format( section=section ) - ) + ), + encoding="utf-8", ) config = pytester.parseconfig() assert config.getini("minversion") == "3.36" @@ -150,7 +152,8 @@ def test_toxini_before_lower_pytestini(self, pytester: Pytester) -> None: [pytest] minversion = 2.0 """ - ) + ), + encoding="utf-8", ) pytester.path.joinpath("pytest.ini").write_text( textwrap.dedent( @@ -158,13 +161,16 @@ def test_toxini_before_lower_pytestini(self, pytester: Pytester) -> None: [pytest] minversion = 1.5 """ - ) + ), + encoding="utf-8", ) config = pytester.parseconfigure(sub) assert config.getini("minversion") == "2.0" def test_ini_parse_error(self, pytester: Pytester) -> None: - pytester.path.joinpath("pytest.ini").write_text("addopts = -x") + pytester.path.joinpath("pytest.ini").write_text( + "addopts = -x", encoding="utf-8" + ) result = pytester.runpytest() assert result.ret != 0 result.stderr.fnmatch_lines("ERROR: *pytest.ini:1: no section header defined") @@ -634,7 +640,7 @@ def test_getoption(self, pytester: Pytester) -> None: def test_getconftest_pathlist(self, pytester: Pytester, tmp_path: Path) -> None: somepath = tmp_path.joinpath("x", "y", "z") p = tmp_path.joinpath("conftest.py") - p.write_text(f"mylist = {['.', str(somepath)]}") + p.write_text(f"mylist = {['.', str(somepath)]}", encoding="utf-8") config = pytester.parseconfigure(p) assert ( config._getconftest_pathlist("notexist", path=tmp_path, rootpath=tmp_path) @@ -910,7 +916,8 @@ def test_inifilename(self, tmp_path: Path) -> None: [pytest] name = value """ - ) + ), + encoding="utf-8", ) inifilename = "../../foo/bar.ini" @@ -927,7 +934,8 @@ def test_inifilename(self, tmp_path: Path) -> None: name = wrong-value should_not_be_set = true """ - ) + ), + encoding="utf-8", ) with MonkeyPatch.context() as mp: mp.chdir(cwd) @@ -1387,7 +1395,7 @@ def test_simple_noini(self, tmp_path: Path, monkeypatch: MonkeyPatch) -> None: ) def test_with_ini(self, tmp_path: Path, name: str, contents: str) -> None: inipath = tmp_path / name - inipath.write_text(contents, "utf-8") + inipath.write_text(contents, encoding="utf-8") a = tmp_path / "a" a.mkdir() @@ -1446,7 +1454,7 @@ def test_with_specific_inifile( ) -> None: p = tmp_path / name p.touch() - p.write_text(contents, "utf-8") + p.write_text(contents, encoding="utf-8") rootpath, inipath, ini_config = determine_setup(str(p), [str(tmp_path)]) assert rootpath == tmp_path assert inipath == p @@ -1542,7 +1550,8 @@ def test_override_ini_names(self, pytester: Pytester, name: str) -> None: custom = 1.0""".format( section=section ) - ) + ), + encoding="utf-8", ) pytester.makeconftest( """ diff --git a/testing/test_conftest.py b/testing/test_conftest.py index f857cde04ba..7ec9feb8bf4 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -47,8 +47,12 @@ def basedir( ) -> Generator[Path, None, None]: tmp_path = tmp_path_factory.mktemp("basedir", numbered=True) tmp_path.joinpath("adir/b").mkdir(parents=True) - tmp_path.joinpath("adir/conftest.py").write_text("a=1 ; Directory = 3") - tmp_path.joinpath("adir/b/conftest.py").write_text("b=2 ; a = 1.5") + tmp_path.joinpath("adir/conftest.py").write_text( + "a=1 ; Directory = 3", encoding="utf-8" + ) + tmp_path.joinpath("adir/b/conftest.py").write_text( + "b=2 ; a = 1.5", encoding="utf-8" + ) if request.param == "inpackage": tmp_path.joinpath("adir/__init__.py").touch() tmp_path.joinpath("adir/b/__init__.py").touch() @@ -123,8 +127,12 @@ def test_value_access_with_confmod(self, basedir: Path) -> None: def test_conftest_in_nonpkg_with_init(tmp_path: Path, _sys_snapshot) -> None: tmp_path.joinpath("adir-1.0/b").mkdir(parents=True) - tmp_path.joinpath("adir-1.0/conftest.py").write_text("a=1 ; Directory = 3") - tmp_path.joinpath("adir-1.0/b/conftest.py").write_text("b=2 ; a = 1.5") + tmp_path.joinpath("adir-1.0/conftest.py").write_text( + "a=1 ; Directory = 3", encoding="utf-8" + ) + tmp_path.joinpath("adir-1.0/b/conftest.py").write_text( + "b=2 ; a = 1.5", encoding="utf-8" + ) tmp_path.joinpath("adir-1.0/b/__init__.py").touch() tmp_path.joinpath("adir-1.0/__init__.py").touch() ConftestWithSetinitial(tmp_path.joinpath("adir-1.0", "b")) @@ -167,7 +175,7 @@ def test_conftest_global_import(pytester: Pytester) -> None: sub = Path("sub") sub.mkdir() subconf = sub / "conftest.py" - subconf.write_text("y=4") + subconf.write_text("y=4", encoding="utf-8") mod2 = conf._importconftest(subconf, importmode="prepend", rootpath=Path.cwd()) assert mod != mod2 assert mod2.y == 4 @@ -246,7 +254,8 @@ def test_conftest_confcutdir(pytester: Pytester) -> None: def pytest_addoption(parser): parser.addoption("--xyz", action="store_true") """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("-h", "--confcutdir=%s" % x, x) result.stdout.fnmatch_lines(["*--xyz*"]) @@ -274,9 +283,12 @@ def test_installed_conftest_is_picked_up(pytester: Pytester, tmp_path: Path) -> @pytest.fixture def fix(): return None """ - ) + ), + encoding="utf-8", + ) + tmp_path.joinpath("foo", "test_it.py").write_text( + "def test_it(fix): pass", encoding="utf-8" ) - tmp_path.joinpath("foo", "test_it.py").write_text("def test_it(fix): pass") result = pytester.runpytest("--pyargs", "foo") assert result.ret == 0 @@ -401,7 +413,8 @@ def test_conftest_existing_junitxml(pytester: Pytester) -> None: def pytest_addoption(parser): parser.addoption("--xyz", action="store_true") """ - ) + ), + encoding="utf-8", ) pytester.makefile(ext=".xml", junit="") # Writes junit.xml result = pytester.runpytest("-h", "--junitxml", "junit.xml") @@ -412,7 +425,7 @@ def test_conftest_import_order(pytester: Pytester, monkeypatch: MonkeyPatch) -> ct1 = pytester.makeconftest("") sub = pytester.mkdir("sub") ct2 = sub / "conftest.py" - ct2.write_text("") + ct2.write_text("", encoding="utf-8") def impct(p, importmode, root): return p @@ -450,7 +463,8 @@ def foo(): def bar(foo): return 'bar' """ - ) + ), + encoding="utf-8", ) subsub = sub.joinpath("subsub") subsub.mkdir() @@ -467,7 +481,8 @@ def bar(): def test_event_fixture(bar): assert bar == 'sub bar' """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("sub") result.stdout.fnmatch_lines(["*1 passed*"]) @@ -481,10 +496,11 @@ def test_conftest_found_with_double_dash(pytester: Pytester) -> None: def pytest_addoption(parser): parser.addoption("--hello-world", action="store_true") """ - ) + ), + encoding="utf-8", ) p = sub.joinpath("test_hello.py") - p.write_text("def test_hello(): pass") + p.write_text("def test_hello(): pass", encoding="utf-8") result = pytester.runpytest(str(p) + "::test_hello", "-h") result.stdout.fnmatch_lines( """ @@ -508,7 +524,8 @@ def _setup_tree(self, pytester: Pytester) -> Dict[str, Path]: # for issue616 def fxtr(): return "from-package" """ - ) + ), + encoding="utf-8", ) package.joinpath("test_pkgroot.py").write_text( textwrap.dedent( @@ -516,7 +533,8 @@ def fxtr(): def test_pkgroot(fxtr): assert fxtr == "from-package" """ - ) + ), + encoding="utf-8", ) swc = package.joinpath("swc") @@ -530,7 +548,8 @@ def test_pkgroot(fxtr): def fxtr(): return "from-swc" """ - ) + ), + encoding="utf-8", ) swc.joinpath("test_with_conftest.py").write_text( textwrap.dedent( @@ -538,7 +557,8 @@ def fxtr(): def test_with_conftest(fxtr): assert fxtr == "from-swc" """ - ) + ), + encoding="utf-8", ) snc = package.joinpath("snc") @@ -551,7 +571,8 @@ def test_no_conftest(fxtr): assert fxtr == "from-package" # No local conftest.py, so should # use value from parent dir's """ - ) + ), + encoding="utf-8", ) print("created directory structure:") for x in pytester.path.glob("**/"): @@ -625,7 +646,8 @@ def test_search_conftest_up_to_inifile( @pytest.fixture def fix1(): pass """ - ) + ), + encoding="utf-8", ) src.joinpath("test_foo.py").write_text( textwrap.dedent( @@ -635,7 +657,8 @@ def test_1(fix1): def test_2(out_of_reach): pass """ - ) + ), + encoding="utf-8", ) root.joinpath("conftest.py").write_text( textwrap.dedent( @@ -644,7 +667,8 @@ def test_2(out_of_reach): @pytest.fixture def out_of_reach(): pass """ - ) + ), + encoding="utf-8", ) args = [str(src)] @@ -727,7 +751,8 @@ def test_required_option_help(pytester: Pytester) -> None: def pytest_addoption(parser): parser.addoption("--xyz", action="store_true", required=True) """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("-h", x) result.stdout.no_fnmatch_line("*argument --xyz is required*") diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d2944fa2bcf..dfe569987ca 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -357,7 +357,8 @@ def test(self): >>> 1/0 ''' """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("--doctest-modules") result.stdout.fnmatch_lines( @@ -448,7 +449,8 @@ def test_doctest_unex_importerror_with_module(self, pytester: Pytester): """\ import asdalsdkjaslkdjasd """ - ) + ), + encoding="utf-8", ) pytester.maketxtfile( """ @@ -492,7 +494,8 @@ def somefunc(): 2 ''' """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest(p, "--doctest-modules") result.stdout.fnmatch_lines( @@ -1566,7 +1569,9 @@ def test_warning_on_unwrap_of_broken_object( def test_is_setup_py_not_named_setup_py(tmp_path: Path) -> None: not_setup_py = tmp_path.joinpath("not_setup.py") - not_setup_py.write_text('from setuptools import setup; setup(name="foo")') + not_setup_py.write_text( + 'from setuptools import setup; setup(name="foo")', encoding="utf-8" + ) assert not _is_setup_py(not_setup_py) diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 500e244531a..8a9dd600b64 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -324,7 +324,8 @@ def test_importerror(pytester: Pytester) -> None: x = 1 """ - ) + ), + encoding="utf-8", ) pytester.path.joinpath("test_importerror.py").write_text( textwrap.dedent( @@ -332,7 +333,8 @@ def test_importerror(pytester: Pytester) -> None: def test_importerror(monkeypatch): monkeypatch.setattr('package.a.x', 2) """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest() result.stdout.fnmatch_lines( @@ -434,11 +436,13 @@ def test_syspath_prepend_with_namespace_packages( ns = d.joinpath("ns_pkg") ns.mkdir() ns.joinpath("__init__.py").write_text( - "__import__('pkg_resources').declare_namespace(__name__)" + "__import__('pkg_resources').declare_namespace(__name__)", encoding="utf-8" ) lib = ns.joinpath(dirname) lib.mkdir() - lib.joinpath("__init__.py").write_text("def check(): return %r" % dirname) + lib.joinpath("__init__.py").write_text( + "def check(): return %r" % dirname, encoding="utf-8" + ) monkeypatch.syspath_prepend("hello") import ns_pkg.hello diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 481d7a606b0..0fd372b518b 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -100,13 +100,13 @@ def preserve_sys(self): def setuptestfs(self, path: Path) -> None: # print "setting up test fs for", repr(path) samplefile = path / "samplefile" - samplefile.write_text("samplefile\n") + samplefile.write_text("samplefile\n", encoding="utf-8") execfile = path / "execfile" - execfile.write_text("x=42") + execfile.write_text("x=42", encoding="utf-8") execfilepy = path / "execfile.py" - execfilepy.write_text("x=42") + execfilepy.write_text("x=42", encoding="utf-8") d = {1: 2, "hello": "world", "answer": 42} path.joinpath("samplepickle").write_bytes(pickle.dumps(d, 1)) diff --git a/tox.ini b/tox.ini index 88ae16dea0c..05c1842af8a 100644 --- a/tox.ini +++ b/tox.ini @@ -38,6 +38,10 @@ passenv = setenv = _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} + # See https://docs.python.org/3/library/io.html#io-encoding-warning + # If we don't enable this, neither can any of our downstream users! + PYTHONWARNDEFAULTENCODING=1 + # Configuration to run with coverage similar to CI, e.g. # "tox -e py37-coverage". coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m From 7e510769b4a9b67ef3802a894b36e7978fa222f8 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 20 Jun 2023 04:55:39 -0700 Subject: [PATCH 112/157] Encoding for subprocess.run --- src/_pytest/pytester.py | 2 ++ testing/test_parseopt.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index a9299944dec..3df52ebe88c 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -6,6 +6,7 @@ import contextlib import gc import importlib +import locale import os import platform import re @@ -129,6 +130,7 @@ def get_open_files(self) -> List[Tuple[str, str]]: stderr=subprocess.DEVNULL, check=True, text=True, + encoding=locale.getpreferredencoding(False), ).stdout def isopen(line: str) -> bool: diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 992f49bc53c..c051ec33834 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -1,4 +1,5 @@ import argparse +import locale import os import shlex import subprocess @@ -289,6 +290,10 @@ def test_multiple_metavar_help(self, parser: parseopt.Parser) -> None: def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: + try: + encoding = locale.getencoding() # New in Python 3.11, ignores utf-8 mode + except AttributeError: + encoding = locale.getpreferredencoding(False) try: bash_version = subprocess.run( ["bash", "--version"], @@ -296,6 +301,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: stderr=subprocess.DEVNULL, check=True, text=True, + encoding=encoding, ).stdout except (OSError, subprocess.CalledProcessError): pytest.skip("bash is not available") From 661b938fcad0ece7d017d76d412fff220e43a865 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 20 Jun 2023 04:55:40 -0700 Subject: [PATCH 113/157] Add encoding in more tests --- scripts/towncrier-draft-to-file.py | 4 +- testing/_py/test_local.py | 98 ++++++++++++++++++------------ testing/acceptance_test.py | 23 ++++--- testing/code/test_excinfo.py | 6 +- testing/code/test_source.py | 2 +- testing/logging/test_reporting.py | 18 +++--- testing/python/collect.py | 47 +++++++++----- testing/test_assertion.py | 8 +-- testing/test_assertrewrite.py | 2 +- testing/test_cacheprovider.py | 13 ++-- testing/test_capture.py | 13 ++-- testing/test_collection.py | 21 ++++--- testing/test_conftest.py | 2 +- testing/test_junitxml.py | 12 ++-- testing/test_link_resolve.py | 3 +- testing/test_monkeypatch.py | 2 +- testing/test_parseopt.py | 2 +- testing/test_pathlib.py | 26 +++++--- testing/test_pluginmanager.py | 2 +- testing/test_pytester.py | 2 +- testing/test_reports.py | 2 +- testing/test_session.py | 12 ++-- testing/test_skipping.py | 21 ++++--- testing/test_stepwise.py | 2 +- testing/test_terminal.py | 8 ++- testing/test_tmpdir.py | 2 +- testing/test_warnings.py | 4 +- 27 files changed, 213 insertions(+), 144 deletions(-) diff --git a/scripts/towncrier-draft-to-file.py b/scripts/towncrier-draft-to-file.py index 81507b40b75..1f1068689a8 100644 --- a/scripts/towncrier-draft-to-file.py +++ b/scripts/towncrier-draft-to-file.py @@ -7,7 +7,9 @@ def main(): Platform agnostic wrapper script for towncrier. Fixes the issue (#7251) where windows users are unable to natively run tox -e docs to build pytest docs. """ - with open("doc/en/_changelog_towncrier_draft.rst", "w") as draft_file: + with open( + "doc/en/_changelog_towncrier_draft.rst", "w", encoding="utf-8" + ) as draft_file: return call(("towncrier", "--draft"), stdout=draft_file) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index b463d769d4c..348682b5396 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1,7 +1,9 @@ +import contextlib import multiprocessing import os import sys import time +import warnings from unittest import mock import pytest @@ -9,6 +11,14 @@ from py.path import local +@contextlib.contextmanager +def ignore_encoding_warning(): + with warnings.catch_warnings(): + with contextlib.suppress(NameError): # new in 3.10 + warnings.simplefilter("ignore", EncodingWarning) + yield + + class CommonFSTests: def test_constructor_equality(self, path1): p = path1.__class__(path1) @@ -223,7 +233,8 @@ def test_cmp(self, path1): assert not (path1 < path1) def test_simple_read(self, path1): - x = path1.join("samplefile").read("r") + with ignore_encoding_warning(): + x = path1.join("samplefile").read("r") assert x == "samplefile\n" def test_join_div_operator(self, path1): @@ -265,12 +276,14 @@ def test_newext(self, path1): def test_readlines(self, path1): fn = path1.join("samplefile") - contents = fn.readlines() + with ignore_encoding_warning(): + contents = fn.readlines() assert contents == ["samplefile\n"] def test_readlines_nocr(self, path1): fn = path1.join("samplefile") - contents = fn.readlines(cr=0) + with ignore_encoding_warning(): + contents = fn.readlines(cr=0) assert contents == ["samplefile", ""] def test_file(self, path1): @@ -362,8 +375,8 @@ def test_copy_file(self, path1): initpy.copy(copied) try: assert copied.check() - s1 = initpy.read() - s2 = copied.read() + s1 = initpy.read_text(encoding="utf-8") + s2 = copied.read_text(encoding="utf-8") assert s1 == s2 finally: if copied.check(): @@ -376,8 +389,8 @@ def test_copy_dir(self, path1): otherdir.copy(copied) assert copied.check(dir=1) assert copied.join("__init__.py").check(file=1) - s1 = otherdir.join("__init__.py").read() - s2 = copied.join("__init__.py").read() + s1 = otherdir.join("__init__.py").read_text(encoding="utf-8") + s2 = copied.join("__init__.py").read_text(encoding="utf-8") assert s1 == s2 finally: if copied.check(dir=1): @@ -463,13 +476,13 @@ def setuptestfs(path): return # print "setting up test fs for", repr(path) samplefile = path.ensure("samplefile") - samplefile.write("samplefile\n") + samplefile.write_text("samplefile\n", encoding="utf-8") execfile = path.ensure("execfile") - execfile.write("x=42") + execfile.write_text("x=42", encoding="utf-8") execfilepy = path.ensure("execfile.py") - execfilepy.write("x=42") + execfilepy.write_text("x=42", encoding="utf-8") d = {1: 2, "hello": "world", "answer": 42} path.ensure("samplepickle").dump(d) @@ -481,22 +494,24 @@ def setuptestfs(path): otherdir.ensure("__init__.py") module_a = otherdir.ensure("a.py") - module_a.write("from .b import stuff as result\n") + module_a.write_text("from .b import stuff as result\n", encoding="utf-8") module_b = otherdir.ensure("b.py") - module_b.write('stuff="got it"\n') + module_b.write_text('stuff="got it"\n', encoding="utf-8") module_c = otherdir.ensure("c.py") - module_c.write( + module_c.write_text( """import py; import otherdir.a value = otherdir.a.result -""" +""", + encoding="utf-8", ) module_d = otherdir.ensure("d.py") - module_d.write( + module_d.write_text( """import py; from otherdir import a value2 = a.result -""" +""", + encoding="utf-8", ) @@ -534,9 +549,11 @@ def batch_make_numbered_dirs(rootdir, repeats): for i in range(repeats): dir_ = local.make_numbered_dir(prefix="repro-", rootdir=rootdir) file_ = dir_.join("foo") - file_.write("%s" % i) - actual = int(file_.read()) - assert actual == i, f"int(file_.read()) is {actual} instead of {i}" + file_.write_text("%s" % i, encoding="utf-8") + actual = int(file_.read_text(encoding="utf-8")) + assert ( + actual == i + ), f"int(file_.read_text(encoding='utf-8')) is {actual} instead of {i}" dir_.join(".lock").remove(ignore_errors=True) return True @@ -692,14 +709,14 @@ def test_gt_with_strings(self, path1): def test_open_and_ensure(self, path1): p = path1.join("sub1", "sub2", "file") - with p.open("w", ensure=1) as f: + with p.open("w", ensure=1, encoding="utf-8") as f: f.write("hello") - assert p.read() == "hello" + assert p.read_text(encoding="utf-8") == "hello" def test_write_and_ensure(self, path1): p = path1.join("sub1", "sub2", "file") - p.write("hello", ensure=1) - assert p.read() == "hello" + p.write_text("hello", ensure=1, encoding="utf-8") + assert p.read_text(encoding="utf-8") == "hello" @pytest.mark.parametrize("bin", (False, True)) def test_dump(self, tmpdir, bin): @@ -770,9 +787,9 @@ def test_ensure_filepath_withdir(self, tmpdir): newfile = tmpdir.join("test1", "test") newfile.ensure() assert newfile.check(file=1) - newfile.write("42") + newfile.write_text("42", encoding="utf-8") newfile.ensure() - s = newfile.read() + s = newfile.read_text(encoding="utf-8") assert s == "42" def test_ensure_filepath_withoutdir(self, tmpdir): @@ -806,9 +823,9 @@ def test_long_filenames(self, tmpdir): newfilename = "/test" * 60 # type:ignore[unreachable] l1 = tmpdir.join(newfilename) l1.ensure(file=True) - l1.write("foo") + l1.write_text("foo", encoding="utf-8") l2 = tmpdir.join(newfilename) - assert l2.read() == "foo" + assert l2.read_text(encoding="utf-8") == "foo" def test_visit_depth_first(self, tmpdir): tmpdir.ensure("a", "1") @@ -1278,14 +1295,14 @@ class TestPOSIXLocalPath: def test_hardlink(self, tmpdir): linkpath = tmpdir.join("test") filepath = tmpdir.join("file") - filepath.write("Hello") + filepath.write_text("Hello", encoding="utf-8") nlink = filepath.stat().nlink linkpath.mklinkto(filepath) assert filepath.stat().nlink == nlink + 1 def test_symlink_are_identical(self, tmpdir): filepath = tmpdir.join("file") - filepath.write("Hello") + filepath.write_text("Hello", encoding="utf-8") linkpath = tmpdir.join("test") linkpath.mksymlinkto(filepath) assert linkpath.readlink() == str(filepath) @@ -1293,7 +1310,7 @@ def test_symlink_are_identical(self, tmpdir): def test_symlink_isfile(self, tmpdir): linkpath = tmpdir.join("test") filepath = tmpdir.join("file") - filepath.write("") + filepath.write_text("", encoding="utf-8") linkpath.mksymlinkto(filepath) assert linkpath.check(file=1) assert not linkpath.check(link=0, file=1) @@ -1302,10 +1319,12 @@ def test_symlink_isfile(self, tmpdir): def test_symlink_relative(self, tmpdir): linkpath = tmpdir.join("test") filepath = tmpdir.join("file") - filepath.write("Hello") + filepath.write_text("Hello", encoding="utf-8") linkpath.mksymlinkto(filepath, absolute=False) assert linkpath.readlink() == "file" - assert filepath.read() == linkpath.read() + assert filepath.read_text(encoding="utf-8") == linkpath.read_text( + encoding="utf-8" + ) def test_symlink_not_existing(self, tmpdir): linkpath = tmpdir.join("testnotexisting") @@ -1338,7 +1357,7 @@ def test_symlink_remove(self, tmpdir): def test_realpath_file(self, tmpdir): linkpath = tmpdir.join("test") filepath = tmpdir.join("file") - filepath.write("") + filepath.write_text("", encoding="utf-8") linkpath.mksymlinkto(filepath) realpath = linkpath.realpath() assert realpath.basename == "file" @@ -1383,7 +1402,7 @@ def test_atime(self, tmpdir): atime1 = path.atime() # we could wait here but timer resolution is very # system dependent - path.read() + path.read_binary() time.sleep(ATIME_RESOLUTION) atime2 = path.atime() time.sleep(ATIME_RESOLUTION) @@ -1467,7 +1486,7 @@ def test_copy_stat_dir(self, tmpdir): test_files = ["a", "b", "c"] src = tmpdir.join("src") for f in test_files: - src.join(f).write(f, ensure=True) + src.join(f).write_text(f, ensure=True, encoding="utf-8") dst = tmpdir.join("dst") # a small delay before the copy time.sleep(ATIME_RESOLUTION) @@ -1521,10 +1540,11 @@ def test_listdir(self, tmpdir): def test_read_write(self, tmpdir): x = tmpdir.join("hello") part = "hällo" - x.write(part) - assert x.read() == part - x.write(part.encode(sys.getdefaultencoding())) - assert x.read() == part.encode(sys.getdefaultencoding()) + with ignore_encoding_warning(): + x.write(part) + assert x.read() == part + x.write(part.encode(sys.getdefaultencoding())) + assert x.read() == part.encode(sys.getdefaultencoding()) class TestBinaryAndTextMethods: diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 0046d05b8b2..5658f2fd6b8 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -613,7 +613,7 @@ def test_pyargs_only_imported_once(self, pytester: Pytester) -> None: def test_pyargs_filename_looks_like_module(self, pytester: Pytester) -> None: pytester.path.joinpath("conftest.py").touch() - pytester.path.joinpath("t.py").write_text("def test(): pass") + pytester.path.joinpath("t.py").write_text("def test(): pass", encoding="utf-8") result = pytester.runpytest("--pyargs", "t.py") assert result.ret == ExitCode.OK @@ -622,8 +622,12 @@ def test_cmdline_python_package(self, pytester: Pytester, monkeypatch) -> None: monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", False) path = pytester.mkpydir("tpkg") - path.joinpath("test_hello.py").write_text("def test_hello(): pass") - path.joinpath("test_world.py").write_text("def test_world(): pass") + path.joinpath("test_hello.py").write_text( + "def test_hello(): pass", encoding="utf-8" + ) + path.joinpath("test_world.py").write_text( + "def test_world(): pass", encoding="utf-8" + ) result = pytester.runpytest("--pyargs", "tpkg") assert result.ret == 0 result.stdout.fnmatch_lines(["*2 passed*"]) @@ -662,13 +666,15 @@ def test_cmdline_python_namespace_package( ns = d.joinpath("ns_pkg") ns.mkdir() ns.joinpath("__init__.py").write_text( - "__import__('pkg_resources').declare_namespace(__name__)" + "__import__('pkg_resources').declare_namespace(__name__)", + encoding="utf-8", ) lib = ns.joinpath(dirname) lib.mkdir() lib.joinpath("__init__.py").touch() lib.joinpath(f"test_{dirname}.py").write_text( - f"def test_{dirname}(): pass\ndef test_other():pass" + f"def test_{dirname}(): pass\ndef test_other():pass", + encoding="utf-8", ) # The structure of the test directory is now: @@ -754,10 +760,10 @@ def test_cmdline_python_package_symlink( lib.mkdir() lib.joinpath("__init__.py").touch() lib.joinpath("test_bar.py").write_text( - "def test_bar(): pass\ndef test_other(a_fixture):pass" + "def test_bar(): pass\ndef test_other(a_fixture):pass", encoding="utf-8" ) lib.joinpath("conftest.py").write_text( - "import pytest\n@pytest.fixture\ndef a_fixture():pass" + "import pytest\n@pytest.fixture\ndef a_fixture():pass", encoding="utf-8" ) d_local = pytester.mkdir("symlink_root") @@ -1276,8 +1282,7 @@ def test_simple(): result.stderr.fnmatch_lines(["*@this is stderr@*"]) # now ensure the output is in the junitxml - with open(pytester.path.joinpath("output.xml")) as f: - fullXml = f.read() + fullXml = pytester.path.joinpath("output.xml").read_text(encoding="utf-8") assert "@this is stdout@\n" in fullXml assert "@this is stderr@\n" in fullXml diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 88aa5f0f154..e5c030c4d66 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -374,7 +374,7 @@ def test_excinfo_no_sourcecode(): def test_excinfo_no_python_sourcecode(tmp_path: Path) -> None: # XXX: simplified locally testable version - tmp_path.joinpath("test.txt").write_text("{{ h()}}:") + tmp_path.joinpath("test.txt").write_text("{{ h()}}:", encoding="utf-8") jinja2 = pytest.importorskip("jinja2") loader = jinja2.FileSystemLoader(str(tmp_path)) @@ -451,7 +451,7 @@ def importasmod(source): source = textwrap.dedent(source) modpath = tmp_path.joinpath("mod.py") tmp_path.joinpath("__init__.py").touch() - modpath.write_text(source) + modpath.write_text(source, encoding="utf-8") importlib.invalidate_caches() return import_path(modpath, root=tmp_path) @@ -1023,7 +1023,7 @@ def f(): """ ) excinfo = pytest.raises(ValueError, mod.f) - tmp_path.joinpath("mod.py").write_text("asdf") + tmp_path.joinpath("mod.py").write_text("asdf", encoding="utf-8") excinfo.traceback = excinfo.traceback.filter(excinfo) repr = excinfo.getrepr() repr.toterminal(tw_mock) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 52417f2f837..dc35c9496ab 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -294,7 +294,7 @@ def method(self): """ ) path = tmp_path.joinpath("a.py") - path.write_text(str(source)) + path.write_text(str(source), encoding="utf-8") mod: Any = import_path(path, root=tmp_path) s2 = Source(mod.A) assert str(source).strip() == str(s2).strip() diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 14b77236ab2..0c8e3fd08a9 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -81,7 +81,7 @@ def test_foo(): # not the info one, because the default level of the root logger is # WARNING. assert os.path.isfile(log_file) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "info text going to logger" not in contents assert "warning text going to logger" in contents @@ -656,7 +656,7 @@ def test_log_file(request): # make sure that we get a '0' exit code for the testsuite assert result.ret == 0 assert os.path.isfile(log_file) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "This log message will be shown" in contents assert "This log message won't be shown" not in contents @@ -687,7 +687,7 @@ def test_log_file(request): # make sure that we get a '0' exit code for the testsuite assert result.ret == 0 assert os.path.isfile(log_file) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "This log message will be shown" in contents assert "This log message won't be shown" not in contents @@ -738,7 +738,7 @@ def test_log_file(request): # make sure that we get a '0' exit code for the testsuite assert result.ret == 0 assert os.path.isfile(log_file) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "This log message will be shown" in contents assert "This log message won't be shown" not in contents @@ -777,7 +777,7 @@ def test_log_file(request): # make sure that we get a '0' exit code for the testsuite assert result.ret == 0 assert os.path.isfile(log_file) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "This log message will be shown" in contents assert "This log message won't be shown" not in contents @@ -985,7 +985,7 @@ def pytest_sessionfinish(session, exitstatus): ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*sessionstart*", "*runtestloop*", "*sessionfinish*"]) - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "sessionstart" in contents assert "runtestloop" in contents @@ -1021,7 +1021,7 @@ def test_first(): """ ) pytester.runpytest() - with open(log_file) as rfh: + with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert contents.count("logreport") == 3 @@ -1065,11 +1065,11 @@ def test_second(): """ ) pytester.runpytest() - with open(os.path.join(report_dir_base, "test_first")) as rfh: + with open(os.path.join(report_dir_base, "test_first"), encoding="utf-8") as rfh: content = rfh.read() assert "message from test 1" in content - with open(os.path.join(report_dir_base, "test_second")) as rfh: + with open(os.path.join(report_dir_base, "test_second"), encoding="utf-8") as rfh: content = rfh.read() assert "message from test 2" in content diff --git a/testing/python/collect.py b/testing/python/collect.py index de10ce4083a..9bf6e00d1f0 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -60,7 +60,8 @@ def test(): """.format( str(root2) ) - ) + ), + encoding="utf-8", ) with monkeypatch.context() as mp: mp.chdir(root2) @@ -832,7 +833,8 @@ def pytest_pycollect_makemodule(): mod = outcome.get_result() mod.obj.hello = "world" """ - ) + ), + encoding="utf-8", ) b.joinpath("test_module.py").write_text( textwrap.dedent( @@ -840,7 +842,8 @@ def pytest_pycollect_makemodule(): def test_hello(): assert hello == "world" """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) @@ -861,7 +864,8 @@ def pytest_pycollect_makeitem(): for func in result: func._some123 = "world" """ - ) + ), + encoding="utf-8", ) b.joinpath("test_module.py").write_text( textwrap.dedent( @@ -874,7 +878,8 @@ def obj(request): def test_hello(obj): assert obj == "world" """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) @@ -974,7 +979,8 @@ def pytest_runtest_call(item): def pytest_runtest_teardown(item): assert item.path.stem == "test_in_sub1" """ - ) + ), + encoding="utf-8", ) sub2.joinpath("conftest.py").write_text( textwrap.dedent( @@ -987,10 +993,11 @@ def pytest_runtest_call(item): def pytest_runtest_teardown(item): assert item.path.stem == "test_in_sub2" """ - ) + ), + encoding="utf-8", ) - sub1.joinpath("test_in_sub1.py").write_text("def test_1(): pass") - sub2.joinpath("test_in_sub2.py").write_text("def test_2(): pass") + sub1.joinpath("test_in_sub1.py").write_text("def test_1(): pass", encoding="utf-8") + sub2.joinpath("test_in_sub2.py").write_text("def test_2(): pass", encoding="utf-8") result = pytester.runpytest("-v", "-s") result.assert_outcomes(passed=2) @@ -1378,7 +1385,8 @@ def test_skip_duplicates_by_default(pytester: Pytester) -> None: def test_real(): pass """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest(str(a), str(a)) result.stdout.fnmatch_lines(["*collected 1 item*"]) @@ -1398,7 +1406,8 @@ def test_keep_duplicates(pytester: Pytester) -> None: def test_real(): pass """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("--keep-duplicates", str(a), str(a)) result.stdout.fnmatch_lines(["*collected 2 item*"]) @@ -1443,8 +1452,12 @@ def test_package_with_modules(pytester: Pytester) -> None: sub2_test = sub2.joinpath("test") sub2_test.mkdir(parents=True) - sub1_test.joinpath("test_in_sub1.py").write_text("def test_1(): pass") - sub2_test.joinpath("test_in_sub2.py").write_text("def test_2(): pass") + sub1_test.joinpath("test_in_sub1.py").write_text( + "def test_1(): pass", encoding="utf-8" + ) + sub2_test.joinpath("test_in_sub2.py").write_text( + "def test_2(): pass", encoding="utf-8" + ) # Execute from . result = pytester.runpytest("-v", "-s") @@ -1488,9 +1501,11 @@ def test_package_ordering(pytester: Pytester) -> None: sub2_test = sub2.joinpath("test") sub2_test.mkdir(parents=True) - root.joinpath("Test_root.py").write_text("def test_1(): pass") - sub1.joinpath("Test_sub1.py").write_text("def test_2(): pass") - sub2_test.joinpath("test_sub2.py").write_text("def test_3(): pass") + root.joinpath("Test_root.py").write_text("def test_1(): pass", encoding="utf-8") + sub1.joinpath("Test_sub1.py").write_text("def test_2(): pass", encoding="utf-8") + sub2_test.joinpath("test_sub2.py").write_text( + "def test_3(): pass", encoding="utf-8" + ) # Execute from . result = pytester.runpytest("-v", "-s") diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 473ae44d98d..7119b3b5aa6 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1392,14 +1392,14 @@ def test_hello(): def test_assertrepr_loaded_per_dir(pytester: Pytester) -> None: pytester.makepyfile(test_base=["def test_base(): assert 1 == 2"]) a = pytester.mkdir("a") - a.joinpath("test_a.py").write_text("def test_a(): assert 1 == 2") + a.joinpath("test_a.py").write_text("def test_a(): assert 1 == 2", encoding="utf-8") a.joinpath("conftest.py").write_text( - 'def pytest_assertrepr_compare(): return ["summary a"]' + 'def pytest_assertrepr_compare(): return ["summary a"]', encoding="utf-8" ) b = pytester.mkdir("b") - b.joinpath("test_b.py").write_text("def test_b(): assert 1 == 2") + b.joinpath("test_b.py").write_text("def test_b(): assert 1 == 2", encoding="utf-8") b.joinpath("conftest.py").write_text( - 'def pytest_assertrepr_compare(): return ["summary b"]' + 'def pytest_assertrepr_compare(): return ["summary b"]', encoding="utf-8" ) result = pytester.runpytest() diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 057b609ac7e..778f843e6cf 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1161,7 +1161,7 @@ def reloaded(): return False def rewrite_self(): - with open(__file__, 'w') as self: + with open(__file__, 'w', encoding='utf-8') as self: self.write('def reloaded(): return True') """, test_fun=""" diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 6f3cccbf1c2..e2e195ca7f5 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -38,7 +38,9 @@ def test_config_cache_dataerror(self, pytester: Pytester) -> None: @pytest.mark.filterwarnings("ignore:could not create cache path") def test_cache_writefail_cachfile_silent(self, pytester: Pytester) -> None: pytester.makeini("[pytest]") - pytester.path.joinpath(".pytest_cache").write_text("gone wrong") + pytester.path.joinpath(".pytest_cache").write_text( + "gone wrong", encoding="utf-8" + ) config = pytester.parseconfigure() cache = config.cache assert cache is not None @@ -1134,7 +1136,9 @@ def test_1(): assert 1 ["*test_2/test_2.py::test_1 PASSED*", "*test_1/test_1.py::test_1 PASSED*"] ) - p1.write_text("def test_1(): assert 1\n" "def test_2(): assert 1\n") + p1.write_text( + "def test_1(): assert 1\n" "def test_2(): assert 1\n", encoding="utf-8" + ) os.utime(p1, ns=(p1.stat().st_atime_ns, int(1e9))) result = pytester.runpytest("--nf", "--collect-only", "-q") @@ -1207,7 +1211,8 @@ def test_1(num): assert num p1.write_text( "import pytest\n" "@pytest.mark.parametrize('num', [1, 2, 3])\n" - "def test_1(num): assert num\n" + "def test_1(num): assert num\n", + encoding="utf-8", ) os.utime(p1, ns=(p1.stat().st_atime_ns, int(1e9))) @@ -1259,7 +1264,7 @@ def test_gitignore(pytester: Pytester) -> None: assert gitignore_path.read_text(encoding="UTF-8") == msg # Does not overwrite existing/custom one. - gitignore_path.write_text("custom") + gitignore_path.write_text("custom", encoding="utf-8") cache.set("something", "else") assert gitignore_path.read_text(encoding="UTF-8") == "custom" diff --git a/testing/test_capture.py b/testing/test_capture.py index 5d6ef64ef71..b6ea8161356 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -750,9 +750,10 @@ def test_setup_failure_does_not_kill_capturing(pytester: Pytester) -> None: def pytest_runtest_setup(item): raise ValueError(42) """ - ) + ), + encoding="utf-8", ) - sub1.joinpath("test_mod.py").write_text("def test_func1(): pass") + sub1.joinpath("test_mod.py").write_text("def test_func1(): pass", encoding="utf-8") result = pytester.runpytest(pytester.path, "--traceconfig") result.stdout.fnmatch_lines(["*ValueError(42)*", "*1 error*"]) @@ -1523,9 +1524,9 @@ def test_global_capture_with_live_logging(pytester: Pytester) -> None: def pytest_runtest_logreport(report): if "test_global" in report.nodeid: if report.when == "teardown": - with open("caplog", "w") as f: + with open("caplog", "w", encoding="utf-8") as f: f.write(report.caplog) - with open("capstdout", "w") as f: + with open("capstdout", "w", encoding="utf-8") as f: f.write(report.capstdout) """ ) @@ -1555,14 +1556,14 @@ def test_global(fix1): result = pytester.runpytest_subprocess("--log-cli-level=INFO") assert result.ret == 0 - with open("caplog") as f: + with open("caplog", encoding="utf-8") as f: caplog = f.read() assert "fix setup" in caplog assert "something in test" in caplog assert "fix teardown" in caplog - with open("capstdout") as f: + with open("capstdout", encoding="utf-8") as f: capstdout = f.read() assert "fix setup" in capstdout diff --git a/testing/test_collection.py b/testing/test_collection.py index 3e1a044433b..8b0a1ab3650 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1273,7 +1273,8 @@ def test_initial_conftests_with_testpaths(pytester: Pytester) -> None: def pytest_sessionstart(session): raise Exception("pytest_sessionstart hook successfully run") """ - ) + ), + encoding="utf-8", ) pytester.makeini( """ @@ -1369,12 +1370,16 @@ def test_collect_symlink_dir(pytester: Pytester) -> None: def test_collectignore_via_conftest(pytester: Pytester) -> None: """collect_ignore in parent conftest skips importing child (issue #4592).""" tests = pytester.mkpydir("tests") - tests.joinpath("conftest.py").write_text("collect_ignore = ['ignore_me']") + tests.joinpath("conftest.py").write_text( + "collect_ignore = ['ignore_me']", encoding="utf-8" + ) ignore_me = tests.joinpath("ignore_me") ignore_me.mkdir() ignore_me.joinpath("__init__.py").touch() - ignore_me.joinpath("conftest.py").write_text("assert 0, 'should_not_be_called'") + ignore_me.joinpath("conftest.py").write_text( + "assert 0, 'should_not_be_called'", encoding="utf-8" + ) result = pytester.runpytest() assert result.ret == ExitCode.NO_TESTS_COLLECTED @@ -1383,9 +1388,9 @@ def test_collectignore_via_conftest(pytester: Pytester) -> None: def test_collect_pkg_init_and_file_in_args(pytester: Pytester) -> None: subdir = pytester.mkdir("sub") init = subdir.joinpath("__init__.py") - init.write_text("def test_init(): pass") + init.write_text("def test_init(): pass", encoding="utf-8") p = subdir.joinpath("test_file.py") - p.write_text("def test_file(): pass") + p.write_text("def test_file(): pass", encoding="utf-8") # NOTE: without "-o python_files=*.py" this collects test_file.py twice. # This changed/broke with "Add package scoped fixtures #2283" (2b1410895) @@ -1412,7 +1417,7 @@ def test_collect_pkg_init_and_file_in_args(pytester: Pytester) -> None: def test_collect_pkg_init_only(pytester: Pytester) -> None: subdir = pytester.mkdir("sub") init = subdir.joinpath("__init__.py") - init.write_text("def test_init(): pass") + init.write_text("def test_init(): pass", encoding="utf-8") result = pytester.runpytest(str(init)) result.stdout.fnmatch_lines(["*no tests ran in*"]) @@ -1427,7 +1432,7 @@ def test_collect_sub_with_symlinks(use_pkg: bool, pytester: Pytester) -> None: sub = pytester.mkdir("sub") if use_pkg: sub.joinpath("__init__.py").touch() - sub.joinpath("test_file.py").write_text("def test_file(): pass") + sub.joinpath("test_file.py").write_text("def test_file(): pass", encoding="utf-8") # Create a broken symlink. symlink_or_skip("test_doesnotexist.py", sub.joinpath("test_broken.py")) @@ -1465,7 +1470,7 @@ def test_collector_respects_tbstyle(pytester: Pytester) -> None: def test_does_not_eagerly_collect_packages(pytester: Pytester) -> None: pytester.makepyfile("def test(): pass") pydir = pytester.mkpydir("foopkg") - pydir.joinpath("__init__.py").write_text("assert False") + pydir.joinpath("__init__.py").write_text("assert False", encoding="utf-8") result = pytester.runpytest() assert result.ret == ExitCode.OK diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 7ec9feb8bf4..4278315078f 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -638,7 +638,7 @@ def test_search_conftest_up_to_inifile( root = pytester.path src = root.joinpath("src") src.mkdir() - src.joinpath("pytest.ini").write_text("[pytest]") + src.joinpath("pytest.ini").write_text("[pytest]", encoding="utf-8") src.joinpath("conftest.py").write_text( textwrap.dedent( """\ diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 90804c61902..690830329c0 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -28,7 +28,7 @@ def schema() -> xmlschema.XMLSchema: """Return an xmlschema.XMLSchema object for the junit-10.xsd file.""" fn = Path(__file__).parent / "example_scripts/junit-10.xsd" - with fn.open() as f: + with fn.open(encoding="utf-8") as f: return xmlschema.XMLSchema(f) @@ -45,7 +45,7 @@ def __call__( xml_path = self.pytester.path.joinpath("junit.xml") result = self.pytester.runpytest("--junitxml=%s" % xml_path, *args) if family == "xunit2": - with xml_path.open() as f: + with xml_path.open(encoding="utf-8") as f: self.schema.validate(f) xmldoc = minidom.parse(str(xml_path)) return result, DomNode(xmldoc) @@ -469,7 +469,7 @@ def test_classname_nested_dir( self, pytester: Pytester, run_and_parse: RunAndParse, xunit_family: str ) -> None: p = pytester.mkdir("sub").joinpath("test_hello.py") - p.write_text("def test_func(): 0/0") + p.write_text("def test_func(): 0/0", encoding="utf-8") result, dom = run_and_parse(family=xunit_family) assert result.ret node = dom.find_first_by_tag("testsuite") @@ -987,7 +987,7 @@ def repr_failure(self, excinfo): return "custom item runtest failed" """ ) - pytester.path.joinpath("myfile.xyz").write_text("hello") + pytester.path.joinpath("myfile.xyz").write_text("hello", encoding="utf-8") result, dom = run_and_parse(family=xunit_family) assert result.ret node = dom.find_first_by_tag("testsuite") @@ -1013,7 +1013,7 @@ def test_print_nullbyte(): ) xmlf = pytester.path.joinpath("junit.xml") pytester.runpytest("--junitxml=%s" % xmlf, "-o", "junit_logging=%s" % junit_logging) - text = xmlf.read_text() + text = xmlf.read_text(encoding="utf-8") assert "\x00" not in text if junit_logging == "system-out": assert "#x00" in text @@ -1035,7 +1035,7 @@ def test_print_nullbyte(): ) xmlf = pytester.path.joinpath("junit.xml") pytester.runpytest("--junitxml=%s" % xmlf, "-o", "junit_logging=%s" % junit_logging) - text = xmlf.read_text() + text = xmlf.read_text(encoding="utf-8") if junit_logging == "system-out": assert "#x0" in text if junit_logging == "no": diff --git a/testing/test_link_resolve.py b/testing/test_link_resolve.py index 60a86ada36e..1ac3afd09e8 100644 --- a/testing/test_link_resolve.py +++ b/testing/test_link_resolve.py @@ -59,7 +59,8 @@ def test_link_resolve(pytester: Pytester) -> None: def test_foo(): raise AssertionError() """ - ) + ), + encoding="utf-8", ) subst = subst_path_linux diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 8a9dd600b64..8175b5f0fad 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -461,5 +461,5 @@ def test_syspath_prepend_with_namespace_packages( # Should invalidate caches via importlib.invalidate_caches. modules_tmpdir = pytester.mkdir("modules_tmpdir") monkeypatch.syspath_prepend(str(modules_tmpdir)) - modules_tmpdir.joinpath("main_app.py").write_text("app = True") + modules_tmpdir.joinpath("main_app.py").write_text("app = True", encoding="utf-8") from main_app import app # noqa: F401 diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index c051ec33834..1899abe153f 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -311,7 +311,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: script = str(pytester.path.joinpath("test_argcomplete")) - with open(str(script), "w") as fp: + with open(str(script), "w", encoding="utf-8") as fp: # redirect output from argcomplete to stdin and stderr is not trivial # http://stackoverflow.com/q/12589419/1307905 # so we use bash diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 0fd372b518b..56c54e484da 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -120,9 +120,9 @@ def setuptestfs(self, path: Path) -> None: otherdir.joinpath("__init__.py").touch() module_a = otherdir / "a.py" - module_a.write_text("from .b import stuff as result\n") + module_a.write_text("from .b import stuff as result\n", encoding="utf-8") module_b = otherdir / "b.py" - module_b.write_text('stuff="got it"\n') + module_b.write_text('stuff="got it"\n', encoding="utf-8") module_c = otherdir / "c.py" module_c.write_text( dedent( @@ -131,7 +131,8 @@ def setuptestfs(self, path: Path) -> None: import otherdir.a value = otherdir.a.result """ - ) + ), + encoding="utf-8", ) module_d = otherdir / "d.py" module_d.write_text( @@ -141,7 +142,8 @@ def setuptestfs(self, path: Path) -> None: from otherdir import a value2 = a.result """ - ) + ), + encoding="utf-8", ) def test_smoke_test(self, path1: Path) -> None: @@ -283,7 +285,7 @@ def test_invalid_path(self, tmp_path: Path) -> None: def simple_module(self, tmp_path: Path) -> Path: fn = tmp_path / "_src/tests/mymod.py" fn.parent.mkdir(parents=True) - fn.write_text("def foo(x): return 40 + x") + fn.write_text("def foo(x): return 40 + x", encoding="utf-8") return fn def test_importmode_importlib(self, simple_module: Path, tmp_path: Path) -> None: @@ -447,7 +449,7 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N return False, even when they are clearly equal. """ module_path = tmp_path.joinpath("my_module.py") - module_path.write_text("def foo(): return 42") + module_path.write_text("def foo(): return 42", encoding="utf-8") monkeypatch.syspath_prepend(tmp_path) with monkeypatch.context() as mp: @@ -473,7 +475,8 @@ def test_importmode_importlib_with_dataclass(self, tmp_path: Path) -> None: class Data: value: str """ - ) + ), + encoding="utf-8", ) module = import_path(fn, mode="importlib", root=tmp_path) @@ -498,7 +501,8 @@ def round_trip(): s = pickle.dumps(_action) return pickle.loads(s) """ - ) + ), + encoding="utf-8", ) module = import_path(fn, mode="importlib", root=tmp_path) @@ -525,7 +529,8 @@ def test_importmode_importlib_with_pickle_separate_modules( class Data: x: int = 42 """ - ) + ), + encoding="utf-8", ) fn2 = tmp_path.joinpath("_src/m2/tests/test.py") @@ -540,7 +545,8 @@ class Data: class Data: x: str = "" """ - ) + ), + encoding="utf-8", ) import pickle diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 9fe23d17792..c6f518b1da2 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -347,7 +347,7 @@ def test_import_plugin_dotted_name( pytest.raises(ImportError, pytestpm.import_plugin, "pytest_qweqwex.y") pytester.syspathinsert() - pytester.mkpydir("pkg").joinpath("plug.py").write_text("x=3") + pytester.mkpydir("pkg").joinpath("plug.py").write_text("x=3", encoding="utf-8") pluginname = "pkg.plug" pytestpm.import_plugin(pluginname) mod = pytestpm.get_plugin("pkg.plug") diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 62dad98589d..8f8b4d2914f 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -222,7 +222,7 @@ def test_inline_run_test_module_not_cleaned_up(self, pytester: Pytester) -> None result = pytester.inline_run(str(test_mod)) assert result.ret == ExitCode.OK # rewrite module, now test should fail if module was re-imported - test_mod.write_text("def test_foo(): assert False") + test_mod.write_text("def test_foo(): assert False", encoding="utf-8") result2 = pytester.inline_run(str(test_mod)) assert result2.ret == ExitCode.TESTS_FAILED diff --git a/testing/test_reports.py b/testing/test_reports.py index e101b51dacb..387d2e807ce 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -410,7 +410,7 @@ def test_report_prevent_ConftestImportFailure_hiding_exception( ) -> None: sub_dir = pytester.path.joinpath("ns") sub_dir.mkdir() - sub_dir.joinpath("conftest.py").write_text("import unknown") + sub_dir.joinpath("conftest.py").write_text("import unknown", encoding="utf-8") result = pytester.runpytest_subprocess(".") result.stdout.fnmatch_lines(["E *Error: No module named 'unknown'"]) diff --git a/testing/test_session.py b/testing/test_session.py index f73dc89ef33..48dc08e8c8f 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -265,9 +265,9 @@ def test_plugin_already_exists(pytester: Pytester) -> None: def test_exclude(pytester: Pytester) -> None: hellodir = pytester.mkdir("hello") - hellodir.joinpath("test_hello.py").write_text("x y syntaxerror") + hellodir.joinpath("test_hello.py").write_text("x y syntaxerror", encoding="utf-8") hello2dir = pytester.mkdir("hello2") - hello2dir.joinpath("test_hello2.py").write_text("x y syntaxerror") + hello2dir.joinpath("test_hello2.py").write_text("x y syntaxerror", encoding="utf-8") pytester.makepyfile(test_ok="def test_pass(): pass") result = pytester.runpytest("--ignore=hello", "--ignore=hello2") assert result.ret == 0 @@ -276,13 +276,13 @@ def test_exclude(pytester: Pytester) -> None: def test_exclude_glob(pytester: Pytester) -> None: hellodir = pytester.mkdir("hello") - hellodir.joinpath("test_hello.py").write_text("x y syntaxerror") + hellodir.joinpath("test_hello.py").write_text("x y syntaxerror", encoding="utf-8") hello2dir = pytester.mkdir("hello2") - hello2dir.joinpath("test_hello2.py").write_text("x y syntaxerror") + hello2dir.joinpath("test_hello2.py").write_text("x y syntaxerror", encoding="utf-8") hello3dir = pytester.mkdir("hallo3") - hello3dir.joinpath("test_hello3.py").write_text("x y syntaxerror") + hello3dir.joinpath("test_hello3.py").write_text("x y syntaxerror", encoding="utf-8") subdir = pytester.mkdir("sub") - subdir.joinpath("test_hello4.py").write_text("x y syntaxerror") + subdir.joinpath("test_hello4.py").write_text("x y syntaxerror", encoding="utf-8") pytester.makepyfile(test_ok="def test_pass(): pass") result = pytester.runpytest("--ignore-glob=*h[ea]llo*") assert result.ret == 0 diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 892ed85476b..6b80346108f 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -195,7 +195,8 @@ def test_skipif_markeval_namespace_multiple(self, pytester: Pytester) -> None: def pytest_markeval_namespace(): return {"arg": "root"} """ - ) + ), + encoding="utf-8", ) root.joinpath("test_root.py").write_text( textwrap.dedent( @@ -206,7 +207,8 @@ def pytest_markeval_namespace(): def test_root(): assert False """ - ) + ), + encoding="utf-8", ) foo = root.joinpath("foo") foo.mkdir() @@ -219,7 +221,8 @@ def test_root(): def pytest_markeval_namespace(): return {"arg": "foo"} """ - ) + ), + encoding="utf-8", ) foo.joinpath("test_foo.py").write_text( textwrap.dedent( @@ -230,7 +233,8 @@ def pytest_markeval_namespace(): def test_foo(): assert False """ - ) + ), + encoding="utf-8", ) bar = root.joinpath("bar") bar.mkdir() @@ -243,7 +247,8 @@ def test_foo(): def pytest_markeval_namespace(): return {"arg": "bar"} """ - ) + ), + encoding="utf-8", ) bar.joinpath("test_bar.py").write_text( textwrap.dedent( @@ -254,7 +259,8 @@ def pytest_markeval_namespace(): def test_bar(): assert False """ - ) + ), + encoding="utf-8", ) reprec = pytester.inline_run("-vs", "--capture=no") @@ -629,7 +635,8 @@ def test_strict_xfail(self, pytester: Pytester, strict: bool) -> None: @pytest.mark.xfail(reason='unsupported feature', strict=%s) def test_foo(): - with open('foo_executed', 'w'): pass # make sure test executes + with open('foo_executed', 'w', encoding='utf-8'): + pass # make sure test executes """ % strict ) diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 2094abc4e50..85e38c7d568 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -352,6 +352,6 @@ def test_one(): assert result.ret == 0 assert Path(stepwise_cache_file).exists() - with stepwise_cache_file.open() as file_handle: + with stepwise_cache_file.open(encoding="utf-8") as file_handle: observed_value = file_handle.readlines() assert [expected_value] == observed_value diff --git a/testing/test_terminal.py b/testing/test_terminal.py index c0acb600608..7c2f7c94a50 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -244,7 +244,8 @@ class TestClass(object): def test_method(self): pass """ - ) + ), + encoding="utf-8", ) result = pytester.runpytest("-vv") assert result.ret == 0 @@ -1567,7 +1568,8 @@ def pytest_report_header(config): """ def pytest_report_header(config, start_path): return ["line1", str(start_path)] -""" +""", + encoding="utf-8", ) result = pytester.runpytest("a") result.stdout.fnmatch_lines(["*hello: 42*", "line1", str(pytester.path)]) @@ -1671,7 +1673,7 @@ def test_fdopen_kept_alive_issue124(pytester: Pytester) -> None: import os, sys k = [] def test_open_file_and_keep_alive(capfd): - stdout = os.fdopen(1, 'w', 1) + stdout = os.fdopen(1, 'w', buffering=1, encoding='utf-8') k.append(stdout) def test_close_kept_alive_file(): diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 110a68b278d..1e1446af127 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -561,7 +561,7 @@ def test_basetemp_with_read_only_files(pytester: Pytester) -> None: def test(tmp_path): fn = tmp_path / 'foo.txt' - fn.write_text('hello') + fn.write_text('hello', encoding='utf-8') mode = os.stat(str(fn)).st_mode os.chmod(str(fn), mode & ~stat.S_IREAD) """ diff --git a/testing/test_warnings.py b/testing/test_warnings.py index a1ecba2476e..03846cb30c3 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -810,12 +810,12 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) - pytester.makepyfile( """ def open_file(p): - f = p.open("r") + f = p.open("r", encoding="utf-8") assert p.read_text() == "hello" def test_resource_warning(tmp_path): p = tmp_path.joinpath("foo.txt") - p.write_text("hello") + p.write_text("hello", encoding="utf-8") open_file(p) """ ) From f6b995e9d59a0b7e1e52fb64185e9e1d1dae367d Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 20 Jun 2023 04:55:40 -0700 Subject: [PATCH 114/157] Use utf-8 debug file --- changelog/7781.bugfix.rst | 1 + src/_pytest/helpconfig.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/7781.bugfix.rst diff --git a/changelog/7781.bugfix.rst b/changelog/7781.bugfix.rst new file mode 100644 index 00000000000..191fcd4daf4 --- /dev/null +++ b/changelog/7781.bugfix.rst @@ -0,0 +1 @@ +Fix writing non-encodable text to log file when using ``--debug``. diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 6b6718a7083..430870608bd 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -105,7 +105,7 @@ def pytest_cmdline_parse(): if config.option.debug: # --debug | --debug was provided. path = config.option.debug - debugfile = open(path, "w") + debugfile = open(path, "w", encoding="utf-8") debugfile.write( "versions pytest-%s, " "python-%s\ncwd=%s\nargs=%s\n\n" From d97d44a97af2303eb3f3aea1f16fd834f5415509 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 20 Jun 2023 20:52:59 +0300 Subject: [PATCH 115/157] config: extract initial paths/nodeids args logic to a function Will be reused in the next commit. --- src/_pytest/config/__init__.py | 76 +++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 85d8830e766..686be1277f3 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1223,6 +1223,49 @@ def _validate_args(self, args: List[str], via: str) -> List[str]: return args + def _decide_args( + self, + *, + args: List[str], + pyargs: List[str], + testpaths: List[str], + invocation_dir: Path, + rootpath: Path, + warn: bool, + ) -> Tuple[List[str], ArgsSource]: + """Decide the args (initial paths/nodeids) to use given the relevant inputs. + + :param warn: Whether can issue warnings. + """ + if args: + source = Config.ArgsSource.ARGS + result = args + else: + if invocation_dir == rootpath: + source = Config.ArgsSource.TESTPATHS + if pyargs: + result = testpaths + else: + result = [] + for path in testpaths: + result.extend(sorted(glob.iglob(path, recursive=True))) + if testpaths and not result: + if warn: + warning_text = ( + "No files were found in testpaths; " + "consider removing or adjusting your testpaths configuration. " + "Searching recursively from the current directory instead." + ) + self.issue_config_time_warning( + PytestConfigWarning(warning_text), stacklevel=3 + ) + else: + result = [] + if not result: + source = Config.ArgsSource.INCOVATION_DIR + result = [str(invocation_dir)] + return result, source + def _preparse(self, args: List[str], addopts: bool = True) -> None: if addopts: env_addopts = os.environ.get("PYTEST_ADDOPTS", "") @@ -1371,34 +1414,17 @@ def parse(self, args: List[str], addopts: bool = True) -> None: self.hook.pytest_cmdline_preparse(config=self, args=args) self._parser.after_preparse = True # type: ignore try: - source = Config.ArgsSource.ARGS args = self._parser.parse_setoption( args, self.option, namespace=self.option ) - if not args: - if self.invocation_params.dir == self.rootpath: - source = Config.ArgsSource.TESTPATHS - testpaths: List[str] = self.getini("testpaths") - if self.known_args_namespace.pyargs: - args = testpaths - else: - args = [] - for path in testpaths: - args.extend(sorted(glob.iglob(path, recursive=True))) - if testpaths and not args: - warning_text = ( - "No files were found in testpaths; " - "consider removing or adjusting your testpaths configuration. " - "Searching recursively from the current directory instead." - ) - self.issue_config_time_warning( - PytestConfigWarning(warning_text), stacklevel=3 - ) - if not args: - source = Config.ArgsSource.INCOVATION_DIR - args = [str(self.invocation_params.dir)] - self.args = args - self.args_source = source + self.args, self.args_source = self._decide_args( + args=args, + pyargs=self.known_args_namespace.pyargs, + testpaths=self.getini("testpaths"), + invocation_dir=self.invocation_params.dir, + rootpath=self.rootpath, + warn=True, + ) except PrintHelp: pass From 14890329dcdc37085a8ac9c53ce332df9faead30 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 20 Jun 2023 20:59:22 +0300 Subject: [PATCH 116/157] config: fix the paths considered for initial conftest discovery Fixes #11104. See the issue for a description of the problem. Now, we use the same logic for initial conftest paths as we do for deciding the initial args, which was the idea behind checking `namespace.file_or_dir` and `testpaths` previously. This fixes the issue of `testpaths` being considered for initial conftests even when it's not used for the args. (Another issue in faeb16146b811488ebbcbd17ef6f9102314065b2 was that the `testpaths` were not glob-expanded, this is also fixed.) --- changelog/11104.bugfix.rst | 3 +++ src/_pytest/config/__init__.py | 45 ++++++++++++++++++++++------------ testing/test_collection.py | 7 ++++++ testing/test_conftest.py | 25 ++++++++++--------- 4 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 changelog/11104.bugfix.rst diff --git a/changelog/11104.bugfix.rst b/changelog/11104.bugfix.rst new file mode 100644 index 00000000000..10f0db92515 --- /dev/null +++ b/changelog/11104.bugfix.rst @@ -0,0 +1,3 @@ +Fixed a regression in pytest 7.3.2 which caused to :confval:`testpaths` to be considered for loading initial conftests, +even when it was not utilized (e.g. when explicit paths were given on the command line). +Now the ``testpaths`` are only considered when they are in use. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 686be1277f3..c9a4b7f63cb 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -527,9 +527,12 @@ def pytest_configure(self, config: "Config") -> None: # def _set_initial_conftests( self, - namespace: argparse.Namespace, + args: Sequence[Union[str, Path]], + pyargs: bool, + noconftest: bool, rootpath: Path, - testpaths_ini: Sequence[str], + confcutdir: Optional[Path], + importmode: Union[ImportMode, str], ) -> None: """Load initial conftest files given a preparsed "namespace". @@ -539,17 +542,12 @@ def _set_initial_conftests( common options will not confuse our logic here. """ current = Path.cwd() - self._confcutdir = ( - absolutepath(current / namespace.confcutdir) - if namespace.confcutdir - else None - ) - self._noconftest = namespace.noconftest - self._using_pyargs = namespace.pyargs - testpaths = namespace.file_or_dir + testpaths_ini + self._confcutdir = absolutepath(current / confcutdir) if confcutdir else None + self._noconftest = noconftest + self._using_pyargs = pyargs foundanchor = False - for testpath in testpaths: - path = str(testpath) + for intitial_path in args: + path = str(intitial_path) # remove node-id syntax i = path.find("::") if i != -1: @@ -563,10 +561,10 @@ def _set_initial_conftests( except OSError: # pragma: no cover anchor_exists = False if anchor_exists: - self._try_load_conftest(anchor, namespace.importmode, rootpath) + self._try_load_conftest(anchor, importmode, rootpath) foundanchor = True if not foundanchor: - self._try_load_conftest(current, namespace.importmode, rootpath) + self._try_load_conftest(current, importmode, rootpath) def _is_in_confcutdir(self, path: Path) -> bool: """Whether a path is within the confcutdir. @@ -1140,10 +1138,25 @@ def _processopt(self, opt: "Argument") -> None: @hookimpl(trylast=True) def pytest_load_initial_conftests(self, early_config: "Config") -> None: + # We haven't fully parsed the command line arguments yet, so + # early_config.args it not set yet. But we need it for + # discovering the initial conftests. So "pre-run" the logic here. + # It will be done for real in `parse()`. + args, args_source = early_config._decide_args( + args=early_config.known_args_namespace.file_or_dir, + pyargs=early_config.known_args_namespace.pyargs, + testpaths=early_config.getini("testpaths"), + invocation_dir=early_config.invocation_params.dir, + rootpath=early_config.rootpath, + warn=False, + ) self.pluginmanager._set_initial_conftests( - early_config.known_args_namespace, + args=args, + pyargs=early_config.known_args_namespace.pyargs, + noconftest=early_config.known_args_namespace.noconftest, rootpath=early_config.rootpath, - testpaths_ini=self.getini("testpaths"), + confcutdir=early_config.known_args_namespace.confcutdir, + importmode=early_config.known_args_namespace.importmode, ) def _initini(self, args: Sequence[str]) -> None: diff --git a/testing/test_collection.py b/testing/test_collection.py index bbcb358b6ff..3021398720f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1264,11 +1264,18 @@ def pytest_sessionstart(session): testpaths = some_path """ ) + + # No command line args - falls back to testpaths. result = pytester.runpytest() + assert result.ret == ExitCode.INTERNAL_ERROR result.stdout.fnmatch_lines( "INTERNALERROR* Exception: pytest_sessionstart hook successfully run" ) + # No fallback. + result = pytester.runpytest(".") + assert result.ret == ExitCode.NO_TESTS_COLLECTED + def test_large_option_breaks_initial_conftests(pytester: Pytester) -> None: """Long option values do not break initial conftests handling (#10169).""" diff --git a/testing/test_conftest.py b/testing/test_conftest.py index c64bd11d4ed..f857cde04ba 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,4 +1,3 @@ -import argparse import os import textwrap from pathlib import Path @@ -7,6 +6,8 @@ from typing import Generator from typing import List from typing import Optional +from typing import Sequence +from typing import Union import pytest from _pytest.config import ExitCode @@ -24,18 +25,18 @@ def ConftestWithSetinitial(path) -> PytestPluginManager: def conftest_setinitial( - conftest: PytestPluginManager, args, confcutdir: Optional["os.PathLike[str]"] = None + conftest: PytestPluginManager, + args: Sequence[Union[str, Path]], + confcutdir: Optional[Path] = None, ) -> None: - class Namespace: - def __init__(self) -> None: - self.file_or_dir = args - self.confcutdir = os.fspath(confcutdir) if confcutdir is not None else None - self.noconftest = False - self.pyargs = False - self.importmode = "prepend" - - namespace = cast(argparse.Namespace, Namespace()) - conftest._set_initial_conftests(namespace, rootpath=Path(args[0]), testpaths_ini=[]) + conftest._set_initial_conftests( + args=args, + pyargs=False, + noconftest=False, + rootpath=Path(args[0]), + confcutdir=confcutdir, + importmode="prepend", + ) @pytest.mark.usefixtures("_sys_snapshot") From 1e8135df16fff350d0097a41b739745a9e14edec Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 22 Jun 2023 15:45:20 +0300 Subject: [PATCH 117/157] reference: add note that `pythonpath` does not affect `-p` Fix #11118. --- doc/en/reference/reference.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7107218b38b..c6629db84fa 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1703,6 +1703,11 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] pythonpath = src1 src2 + .. note:: + + ``pythonpath`` does not affect some imports that happen very early, + most notably plugins loaded using the ``-p`` command line option. + .. confval:: required_plugins From d9bf9dbec104af1e3a2c02b04f4e1d501d5d86a2 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Fri, 23 Jun 2023 10:47:41 +0000 Subject: [PATCH 118/157] Prepare release version 7.4.0 [ran: made some fixups] --- changelog/10831.bugfix.rst | 1 - changelog/10872.improvement.rst | 1 - changelog/10901.feature.rst | 2 - changelog/10907.improvement.rst | 5 -- changelog/10940.improvement.rst | 3 - changelog/10991.improvement.rst | 1 - changelog/11005.improvement.rst | 1 - changelog/11013.improvement.rst | 1 - changelog/11031.trivial.rst | 1 - changelog/11043.improvement.rst | 3 - changelog/11068.bugfix.rst | 1 - changelog/11081.improvement.rst | 7 --- changelog/11104.bugfix.rst | 3 - changelog/1904.bugfix.rst | 1 - changelog/7781.bugfix.rst | 1 - changelog/8711.improvement.rst | 3 - changelog/9146.doc.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.0.rst | 49 ++++++++++++++++ doc/en/builtin.rst | 6 +- doc/en/changelog.rst | 92 +++++++++++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- doc/en/reference/reference.rst | 4 +- 23 files changed, 148 insertions(+), 42 deletions(-) delete mode 100644 changelog/10831.bugfix.rst delete mode 100644 changelog/10872.improvement.rst delete mode 100644 changelog/10901.feature.rst delete mode 100644 changelog/10907.improvement.rst delete mode 100644 changelog/10940.improvement.rst delete mode 100644 changelog/10991.improvement.rst delete mode 100644 changelog/11005.improvement.rst delete mode 100644 changelog/11013.improvement.rst delete mode 100644 changelog/11031.trivial.rst delete mode 100644 changelog/11043.improvement.rst delete mode 100644 changelog/11068.bugfix.rst delete mode 100644 changelog/11081.improvement.rst delete mode 100644 changelog/11104.bugfix.rst delete mode 100644 changelog/1904.bugfix.rst delete mode 100644 changelog/7781.bugfix.rst delete mode 100644 changelog/8711.improvement.rst delete mode 100644 changelog/9146.doc.rst create mode 100644 doc/en/announce/release-7.4.0.rst diff --git a/changelog/10831.bugfix.rst b/changelog/10831.bugfix.rst deleted file mode 100644 index ea641dee60e..00000000000 --- a/changelog/10831.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Terminal Reporting: Fixed bug when running in ``--tb=line`` mode where ``pytest.fail(pytrace=False)`` tests report ``None``. diff --git a/changelog/10872.improvement.rst b/changelog/10872.improvement.rst deleted file mode 100644 index fe0c01a0224..00000000000 --- a/changelog/10872.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook. diff --git a/changelog/10901.feature.rst b/changelog/10901.feature.rst deleted file mode 100644 index 0d99d66f67f..00000000000 --- a/changelog/10901.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added :func:`ExceptionInfo.from_exception() `, a simpler way to create an :class:`~pytest.ExceptionInfo` from an exception. -This can replace :func:`ExceptionInfo.from_exc_info() ` for most uses. diff --git a/changelog/10907.improvement.rst b/changelog/10907.improvement.rst deleted file mode 100644 index 7f011a827d3..00000000000 --- a/changelog/10907.improvement.rst +++ /dev/null @@ -1,5 +0,0 @@ -When an exception traceback to be displayed is completely filtered out (by mechanisms such as ``__tracebackhide__``, internal frames, and similar), now only the exception string and the following message are shown: - -"All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames.". - -Previously, the last frame of the traceback was shown, even though it was hidden. diff --git a/changelog/10940.improvement.rst b/changelog/10940.improvement.rst deleted file mode 100644 index f3e33cbc68d..00000000000 --- a/changelog/10940.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improved verbose output (``-vv``) of ``skip`` and ``xfail`` reasons by performing text wrapping while leaving a clear margin for progress output. - -Added :func:`TerminalReporter.wrap_write() ` as a helper for that. diff --git a/changelog/10991.improvement.rst b/changelog/10991.improvement.rst deleted file mode 100644 index 768c08e554c..00000000000 --- a/changelog/10991.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``. diff --git a/changelog/11005.improvement.rst b/changelog/11005.improvement.rst deleted file mode 100644 index 295252514a6..00000000000 --- a/changelog/11005.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added underlying exception to cache provider path creation and write warning messages. diff --git a/changelog/11013.improvement.rst b/changelog/11013.improvement.rst deleted file mode 100644 index fe3ece93c23..00000000000 --- a/changelog/11013.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory. diff --git a/changelog/11031.trivial.rst b/changelog/11031.trivial.rst deleted file mode 100644 index fad2cf24d5a..00000000000 --- a/changelog/11031.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file. diff --git a/changelog/11043.improvement.rst b/changelog/11043.improvement.rst deleted file mode 100644 index 1fe0361d7f9..00000000000 --- a/changelog/11043.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir`. -Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. -If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`. diff --git a/changelog/11068.bugfix.rst b/changelog/11068.bugfix.rst deleted file mode 100644 index 45cdb105fb4..00000000000 --- a/changelog/11068.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the ``--last-failed`` whole-file skipping functionality ("skipped N files") for :ref:`non-python test files `. diff --git a/changelog/11081.improvement.rst b/changelog/11081.improvement.rst deleted file mode 100644 index ccfaf6016ae..00000000000 --- a/changelog/11081.improvement.rst +++ /dev/null @@ -1,7 +0,0 @@ -The :confval:`norecursedir` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. - -If after updating to this version you see that your `norecursedir` setting is not being respected, -it means that a conftest or a plugin you use has a bad `pytest_ignore_collect` implementation. -Most likely, your hook returns `False` for paths it does not want to ignore, -which ends the processing and doesn't allow other plugins, including pytest itself, to ignore the path. -The fix is to return `None` instead of `False` for paths your hook doesn't want to ignore. diff --git a/changelog/11104.bugfix.rst b/changelog/11104.bugfix.rst deleted file mode 100644 index 10f0db92515..00000000000 --- a/changelog/11104.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a regression in pytest 7.3.2 which caused to :confval:`testpaths` to be considered for loading initial conftests, -even when it was not utilized (e.g. when explicit paths were given on the command line). -Now the ``testpaths`` are only considered when they are in use. diff --git a/changelog/1904.bugfix.rst b/changelog/1904.bugfix.rst deleted file mode 100644 index 3e1a292152b..00000000000 --- a/changelog/1904.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message). diff --git a/changelog/7781.bugfix.rst b/changelog/7781.bugfix.rst deleted file mode 100644 index 191fcd4daf4..00000000000 --- a/changelog/7781.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix writing non-encodable text to log file when using ``--debug``. diff --git a/changelog/8711.improvement.rst b/changelog/8711.improvement.rst deleted file mode 100644 index 20805e9f94d..00000000000 --- a/changelog/8711.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`_pytest.logging.LogCaptureFixture.set_level` and :func:`_pytest.logging.LogCaptureFixture.at_level` -will temporarily enable the requested ``level`` if ``level`` was disabled globally via -``logging.disable(LEVEL)``. diff --git a/changelog/9146.doc.rst b/changelog/9146.doc.rst deleted file mode 100644 index 95189b96d46..00000000000 --- a/changelog/9146.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improve Documentation for `caplog.set_level`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index bcc0669a62f..914e763bd9e 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.0 release-7.3.2 release-7.3.1 release-7.3.0 diff --git a/doc/en/announce/release-7.4.0.rst b/doc/en/announce/release-7.4.0.rst new file mode 100644 index 00000000000..5a0d18267d3 --- /dev/null +++ b/doc/en/announce/release-7.4.0.rst @@ -0,0 +1,49 @@ +pytest-7.4.0 +======================================= + +The pytest team is proud to announce the 7.4.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Adam J. Stewart +* Alessio Izzo +* Alex +* Alex Lambson +* Brian Larsen +* Bruno Oliveira +* Bryan Ricker +* Chris Mahoney +* Facundo Batista +* Florian Bruhin +* Jarrett Keifer +* Kenny Y +* Miro Hrončok +* Ran Benita +* Roberto Aldera +* Ronny Pfannschmidt +* Sergey Kim +* Stefanie Molin +* Vijay Arora +* Ville Skyttä +* Zac Hatfield-Dodds +* bzoracler +* leeyueh +* nondescryptid +* theirix + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 7ae185f6c7d..53305eecded 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:510 + cache -- .../_pytest/cacheprovider.py:528 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -119,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1360 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1353 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:498 + caplog -- .../_pytest/logging.py:570 Access and control log capturing. Captured logs are available through the following properties/methods:: diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index cdc9e66f68b..391721df34d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,98 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.0 (2023-06-23) +========================= + +Features +-------- + +- `#10901 `_: Added :func:`ExceptionInfo.from_exception() `, a simpler way to create an :class:`~pytest.ExceptionInfo` from an exception. + This can replace :func:`ExceptionInfo.from_exc_info() ` for most uses. + + + +Improvements +------------ + +- `#10872 `_: Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook. + + +- `#10907 `_: When an exception traceback to be displayed is completely filtered out (by mechanisms such as ``__tracebackhide__``, internal frames, and similar), now only the exception string and the following message are shown: + + "All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames.". + + Previously, the last frame of the traceback was shown, even though it was hidden. + + +- `#10940 `_: Improved verbose output (``-vv``) of ``skip`` and ``xfail`` reasons by performing text wrapping while leaving a clear margin for progress output. + + Added ``TerminalReporter.wrap_write()`` as a helper for that. + + +- `#10991 `_: Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``. + + +- `#11005 `_: Added the underlying exception to the cache provider's path creation and write warning messages. + + +- `#11013 `_: Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory. + + +- `#11043 `_: When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir `. + Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. + If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`. + + +- `#11081 `_: The :confval:`norecursedirs` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. + + If after updating to this version you see that your `norecursedirs` setting is not being respected, + it means that a conftest or a plugin you use has a bad `pytest_ignore_collect` implementation. + Most likely, your hook returns `False` for paths it does not want to ignore, + which ends the processing and doesn't allow other plugins, including pytest itself, to ignore the path. + The fix is to return `None` instead of `False` for paths your hook doesn't want to ignore. + + +- `#8711 `_: :func:`caplog.set_level() ` and :func:`caplog.at_level() ` + will temporarily enable the requested ``level`` if ``level`` was disabled globally via + ``logging.disable(LEVEL)``. + + + +Bug Fixes +--------- + +- `#10831 `_: Terminal Reporting: Fixed bug when running in ``--tb=line`` mode where ``pytest.fail(pytrace=False)`` tests report ``None``. + + +- `#11068 `_: Fixed the ``--last-failed`` whole-file skipping functionality ("skipped N files") for :ref:`non-python test files `. + + +- `#11104 `_: Fixed a regression in pytest 7.3.2 which caused to :confval:`testpaths` to be considered for loading initial conftests, + even when it was not utilized (e.g. when explicit paths were given on the command line). + Now the ``testpaths`` are only considered when they are in use. + + +- `#1904 `_: Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message). + + +- `#7781 `_: Fix writing non-encodable text to log file when using ``--debug``. + + + +Improved Documentation +---------------------- + +- `#9146 `_: Improved documentation for :func:`caplog.set_level() `. + + + +Trivial/Internal Changes +------------------------ + +- `#11031 `_: Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file. + + pytest 7.3.2 (2023-06-10) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 2dbf7d3870c..e295c180454 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 7.3.2 + pytest 7.4.0 .. _`simpletest`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index c6629db84fa..83bbccbcbdc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1923,9 +1923,9 @@ 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, --config-file FILE + -c FILE, --config-file=FILE Load configuration from `FILE` instead of trying to - locate one of the implicit configuration files + locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur --rootdir=ROOTDIR Define root directory for tests. Can be relative From b6c55787fec3a3584ee7f73ada9568708f7c004c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 3 Jul 2023 13:17:02 -0300 Subject: [PATCH 119/157] Switch to deploy environment and configure for pypi oidc (#10925) (#11162) Closes #10871 Closes #10870 Co-authored-by: Ronny Pfannschmidt --- .github/workflows/deploy.yml | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 25280994687..e6b4f0ea2d7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -13,40 +13,54 @@ on: permissions: {} jobs: - - deploy: - if: github.repository == 'pytest-dev/pytest' - + build: runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: write - + timeout-minutes: 10 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 persist-credentials: false - - name: Build and Check Package uses: hynek/build-and-inspect-python-package@v1.5 + deploy: + if: github.repository == 'pytest-dev/pytest' + needs: [build] + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + id-token: write + steps: - name: Download Package uses: actions/download-artifact@v3 with: name: Packages path: dist - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.pypi_token }} + uses: pypa/gh-action-pypi-publish@v1.8.5 + + release-notes: + # todo: generate the content in the build job + # the goal being of using a github action script to push the release data + # after success instead of creating a complete python/tox env + needs: [deploy] + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: write + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false - name: Set up Python uses: actions/setup-python@v4 with: python-version: "3.7" + - name: Install tox run: | python -m pip install --upgrade pip From a4d7254d18a201016b97ce6a6e3f41a124e7e84c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:33:47 +0000 Subject: [PATCH 120/157] [7.4.x] Fix duplicated imports with importlib mode and doctest-modules (#11164) Co-authored-by: Bruno Oliveira --- changelog/10811.bugfix.rst | 2 ++ src/_pytest/pathlib.py | 2 ++ testing/acceptance_test.py | 35 +++++++++++++++++++++++++++++++++++ testing/test_pathlib.py | 27 +++++++++++++++++++-------- 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 changelog/10811.bugfix.rst diff --git a/changelog/10811.bugfix.rst b/changelog/10811.bugfix.rst new file mode 100644 index 00000000000..aa26414e457 --- /dev/null +++ b/changelog/10811.bugfix.rst @@ -0,0 +1,2 @@ +Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules +to be imported more than once, causing problems with modules that have import side effects. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 70383e4b504..e5fdd639a82 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -523,6 +523,8 @@ def import_path( if mode is ImportMode.importlib: module_name = module_name_from_path(path, root) + with contextlib.suppress(KeyError): + return sys.modules[module_name] for meta_importer in sys.meta_path: spec = meta_importer.find_spec(module_name, [str(path.parent)]) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 5658f2fd6b8..ed750a97071 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1317,3 +1317,38 @@ def test_stuff(): ) res = pytester.runpytest() res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"]) + + +def test_doctest_and_normal_imports_with_importlib(pytester: Pytester) -> None: + """ + Regression test for #10811: previously import_path with ImportMode.importlib would + not return a module if already in sys.modules, resulting in modules being imported + multiple times, which causes problems with modules that have import side effects. + """ + # Uses the exact reproducer form #10811, given it is very minimal + # and illustrates the problem well. + pytester.makepyfile( + **{ + "pmxbot/commands.py": "from . import logging", + "pmxbot/logging.py": "", + "tests/__init__.py": "", + "tests/test_commands.py": """ + import importlib + from pmxbot import logging + + class TestCommands: + def test_boo(self): + assert importlib.import_module('pmxbot.logging') is logging + """, + } + ) + pytester.makeini( + """ + [pytest] + addopts= + --doctest-modules + --import-mode importlib + """ + ) + result = pytester.runpytest_subprocess() + result.stdout.fnmatch_lines("*1 passed*") diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 56c54e484da..945d6f7d746 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -7,6 +7,7 @@ from types import ModuleType from typing import Any from typing import Generator +from typing import Iterator import pytest from _pytest.monkeypatch import MonkeyPatch @@ -282,29 +283,36 @@ def test_invalid_path(self, tmp_path: Path) -> None: import_path(tmp_path / "invalid.py", root=tmp_path) @pytest.fixture - def simple_module(self, tmp_path: Path) -> Path: - fn = tmp_path / "_src/tests/mymod.py" + def simple_module( + self, tmp_path: Path, request: pytest.FixtureRequest + ) -> Iterator[Path]: + name = f"mymod_{request.node.name}" + fn = tmp_path / f"_src/tests/{name}.py" fn.parent.mkdir(parents=True) fn.write_text("def foo(x): return 40 + x", encoding="utf-8") - return fn + module_name = module_name_from_path(fn, root=tmp_path) + yield fn + sys.modules.pop(module_name, None) - def test_importmode_importlib(self, simple_module: Path, tmp_path: Path) -> None: + def test_importmode_importlib( + self, simple_module: Path, tmp_path: Path, request: pytest.FixtureRequest + ) -> None: """`importlib` mode does not change sys.path.""" module = import_path(simple_module, mode="importlib", root=tmp_path) assert module.foo(2) == 42 # type: ignore[attr-defined] assert str(simple_module.parent) not in sys.path assert module.__name__ in sys.modules - assert module.__name__ == "_src.tests.mymod" + assert module.__name__ == f"_src.tests.mymod_{request.node.name}" assert "_src" in sys.modules assert "_src.tests" in sys.modules - def test_importmode_twice_is_different_module( + def test_remembers_previous_imports( self, simple_module: Path, tmp_path: Path ) -> None: - """`importlib` mode always returns a new module.""" + """`importlib` mode called remembers previous module (#10341, #10811).""" module1 = import_path(simple_module, mode="importlib", root=tmp_path) module2 = import_path(simple_module, mode="importlib", root=tmp_path) - assert module1 is not module2 + assert module1 is module2 def test_no_meta_path_found( self, simple_module: Path, monkeypatch: MonkeyPatch, tmp_path: Path @@ -317,6 +325,9 @@ def test_no_meta_path_found( # mode='importlib' fails if no spec is found to load the module import importlib.util + # Force module to be re-imported. + del sys.modules[module.__name__] + monkeypatch.setattr( importlib.util, "spec_from_file_location", lambda *args: None ) From d53951836dc2ef6cbc454356243460640737c49b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 21:49:24 +0000 Subject: [PATCH 121/157] [7.4.x] Update open trainings (#11172) Co-authored-by: Florian Bruhin --- doc/en/index.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index de07831ac14..50f3e9c10c3 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,8 +2,9 @@ .. sidebar:: Next Open Trainings - - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, July 18th (3h), Prague/Remote - - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Leipzig/Remote + - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, **July 18th** (3h), **Prague, Czech Republic / Remote** + - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** + - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** Also see :doc:`previous talks and blogposts `. From c71b5df7347a84ef270888c8b93f5c8853ff76f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 15:11:26 -0300 Subject: [PATCH 122/157] [7.4.x] Add child modules as attributes of parent modules. (#11163) * [7.4.x] Add child modules as attributes of parent modules. * Update 10337.bugfix.rst --------- Co-authored-by: akhilramkee <31619526+akhilramkee@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- changelog/10337.bugfix.rst | 2 ++ src/_pytest/pathlib.py | 14 +++++++++++++- testing/test_pathlib.py | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 changelog/10337.bugfix.rst diff --git a/changelog/10337.bugfix.rst b/changelog/10337.bugfix.rst new file mode 100644 index 00000000000..3270016f926 --- /dev/null +++ b/changelog/10337.bugfix.rst @@ -0,0 +1,2 @@ +Fixed bug where fake intermediate modules generated by ``--import-mode=importlib`` would not include the +child modules as attributes of the parent modules. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e5fdd639a82..14fb2e3ae2f 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -635,6 +635,9 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> otherwise "src.tests.test_foo" is not importable by ``__import__``. """ module_parts = module_name.split(".") + child_module: Union[ModuleType, None] = None + module: Union[ModuleType, None] = None + child_name: str = "" while module_name: if module_name not in modules: try: @@ -644,13 +647,22 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> # ourselves to fall back to creating a dummy module. if not sys.meta_path: raise ModuleNotFoundError - importlib.import_module(module_name) + module = importlib.import_module(module_name) except ModuleNotFoundError: module = ModuleType( module_name, doc="Empty module created by pytest's importmode=importlib.", ) + else: + module = modules[module_name] + if child_module: + # Add child attribute to the parent that can reference the child + # modules. + if not hasattr(module, child_name): + setattr(module, child_name, child_module) modules[module_name] = module + # Keep track of the child module while moving up the tree. + child_module, child_name = module, module_name.rpartition(".")[-1] module_parts.pop(-1) module_name = ".".join(module_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 945d6f7d746..3d574e85658 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -603,3 +603,15 @@ def test_insert_missing_modules( modules = {} insert_missing_modules(modules, "") assert modules == {} + + def test_parent_contains_child_module_attribute( + self, monkeypatch: MonkeyPatch, tmp_path: Path + ): + monkeypatch.chdir(tmp_path) + # Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and + # don't end up being imported. + modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")} + insert_missing_modules(modules, "xxx.tests.foo") + assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"] + assert modules["xxx"].tests is modules["xxx.tests"] + assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] From 511adf85beb87c96d6b0c9922a17e3acc4e8713f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 18:37:35 +0000 Subject: [PATCH 123/157] [7.4.x] Fix error assertion handling in approx when None in dict comparison (#11180) Co-authored-by: Zac Hatfield-Dodds --- changelog/10702.bugfix.rst | 1 + src/_pytest/python_api.py | 25 +++++++++++++------------ testing/python/approx.py | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 changelog/10702.bugfix.rst diff --git a/changelog/10702.bugfix.rst b/changelog/10702.bugfix.rst new file mode 100644 index 00000000000..4008cc882ec --- /dev/null +++ b/changelog/10702.bugfix.rst @@ -0,0 +1 @@ +Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 4213bd098c2..183356100c5 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -266,19 +266,20 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]: approx_side_as_map.items(), other_side.values() ): if approx_value != other_value: - max_abs_diff = max( - max_abs_diff, abs(approx_value.expected - other_value) - ) - if approx_value.expected == 0.0: - max_rel_diff = math.inf - else: - max_rel_diff = max( - max_rel_diff, - abs( - (approx_value.expected - other_value) - / approx_value.expected - ), + if approx_value.expected is not None and other_value is not None: + max_abs_diff = max( + max_abs_diff, abs(approx_value.expected - other_value) ) + if approx_value.expected == 0.0: + max_rel_diff = math.inf + else: + max_rel_diff = max( + max_rel_diff, + abs( + (approx_value.expected - other_value) + / approx_value.expected + ), + ) different_ids.append(approx_key) message_data = [ diff --git a/testing/python/approx.py b/testing/python/approx.py index 631e52b56ac..6ad411a3e07 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -122,6 +122,23 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): ], ) + assert_approx_raises_regex( + {"a": 1.0, "b": None, "c": None}, + { + "a": None, + "b": 1000.0, + "c": None, + }, + [ + r" comparison failed. Mismatched elements: 2 / 3:", + r" Max absolute difference: -inf", + r" Max relative difference: -inf", + r" Index \| Obtained\s+\| Expected\s+", + rf" a \| {SOME_FLOAT} \| None", + rf" b \| None\s+\| {SOME_FLOAT} ± {SOME_FLOAT}", + ], + ) + assert_approx_raises_regex( [1.0, 2.0, 3.0, 4.0], [1.0, 3.0, 3.0, 5.0], From a566b78730c6ffad5bee5b41c8d615423a56e836 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 19:07:55 +0000 Subject: [PATCH 124/157] [7.4.x] reference: improve the node types docs a bit (#11181) Co-authored-by: Bruno Oliveira --- doc/en/reference/reference.rst | 138 ++++++++++++++++++--------------- src/_pytest/main.py | 5 ++ src/_pytest/nodes.py | 21 +++-- src/_pytest/python.py | 15 ++-- 4 files changed, 102 insertions(+), 77 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 83bbccbcbdc..9e79397f09d 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -783,25 +783,17 @@ reporting or interaction with exceptions: .. autofunction:: pytest_leave_pdb -Objects -------- - -Full reference to objects accessible from :ref:`fixtures ` or :ref:`hooks `. +Collection tree objects +----------------------- +These are the collector and item classes (collectively called "nodes") which +make up the collection tree. -CallInfo -~~~~~~~~ - -.. autoclass:: pytest.CallInfo() - :members: - - -Class -~~~~~ +Node +~~~~ -.. autoclass:: pytest.Class() +.. autoclass:: _pytest.nodes.Node() :members: - :show-inheritance: Collector ~~~~~~~~~ @@ -810,52 +802,52 @@ Collector :members: :show-inheritance: -CollectReport -~~~~~~~~~~~~~ +Item +~~~~ -.. autoclass:: pytest.CollectReport() +.. autoclass:: pytest.Item() :members: :show-inheritance: - :inherited-members: -Config -~~~~~~ +File +~~~~ -.. autoclass:: pytest.Config() +.. autoclass:: pytest.File() :members: + :show-inheritance: -ExceptionInfo -~~~~~~~~~~~~~ +FSCollector +~~~~~~~~~~~ -.. autoclass:: pytest.ExceptionInfo() +.. autoclass:: _pytest.nodes.FSCollector() :members: + :show-inheritance: +Session +~~~~~~~ -ExitCode -~~~~~~~~ - -.. autoclass:: pytest.ExitCode +.. autoclass:: pytest.Session() :members: + :show-inheritance: -File -~~~~ +Package +~~~~~~~ -.. autoclass:: pytest.File() +.. autoclass:: pytest.Package() :members: :show-inheritance: +Module +~~~~~~ -FixtureDef -~~~~~~~~~~ - -.. autoclass:: _pytest.fixtures.FixtureDef() +.. autoclass:: pytest.Module() :members: :show-inheritance: -FSCollector -~~~~~~~~~~~ +Class +~~~~~ -.. autoclass:: _pytest.nodes.FSCollector() +.. autoclass:: pytest.Class() :members: :show-inheritance: @@ -873,10 +865,52 @@ FunctionDefinition :members: :show-inheritance: -Item -~~~~ -.. autoclass:: pytest.Item() +Objects +------- + +Objects accessible from :ref:`fixtures ` or :ref:`hooks ` +or importable from ``pytest``. + + +CallInfo +~~~~~~~~ + +.. autoclass:: pytest.CallInfo() + :members: + +CollectReport +~~~~~~~~~~~~~ + +.. autoclass:: pytest.CollectReport() + :members: + :show-inheritance: + :inherited-members: + +Config +~~~~~~ + +.. autoclass:: pytest.Config() + :members: + +ExceptionInfo +~~~~~~~~~~~~~ + +.. autoclass:: pytest.ExceptionInfo() + :members: + + +ExitCode +~~~~~~~~ + +.. autoclass:: pytest.ExitCode + :members: + + +FixtureDef +~~~~~~~~~~ + +.. autoclass:: _pytest.fixtures.FixtureDef() :members: :show-inheritance: @@ -907,19 +941,6 @@ Metafunc .. autoclass:: pytest.Metafunc() :members: -Module -~~~~~~ - -.. autoclass:: pytest.Module() - :members: - :show-inheritance: - -Node -~~~~ - -.. autoclass:: _pytest.nodes.Node() - :members: - Parser ~~~~~~ @@ -941,13 +962,6 @@ PytestPluginManager :inherited-members: :show-inheritance: -Session -~~~~~~~ - -.. autoclass:: pytest.Session() - :members: - :show-inheritance: - TestReport ~~~~~~~~~~ diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 155d4300e2c..803b95a2033 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -462,6 +462,11 @@ def __missing__(self, path: Path) -> str: @final class Session(nodes.FSCollector): + """The root of the collection tree. + + ``Session`` collects the initial paths given as arguments to pytest. + """ + Interrupted = Interrupted Failed = Failed # Set on the session by runner.pytest_sessionstart. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index dbd6b0a4273..667a02b77af 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -157,10 +157,11 @@ def _create(self, *k, **kw): class Node(metaclass=NodeMeta): - """Base class for Collector and Item, the components of the test - collection tree. + r"""Base class of :class:`Collector` and :class:`Item`, the components of + the test collection tree. - Collector subclasses have children; Items are leaf nodes. + ``Collector``\'s are the internal nodes of the tree, and ``Item``\'s are the + leaf nodes. """ # Implemented in the legacypath plugin. @@ -525,15 +526,17 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i class Collector(Node): - """Collector instances create children through collect() and thus - iteratively build a tree.""" + """Base class of all collectors. + + Collector create children through `collect()` and thus iteratively build + the collection tree. + """ class CollectError(Exception): """An error during collection, contains a custom message.""" def collect(self) -> Iterable[Union["Item", "Collector"]]: - """Return a list of children (items and collectors) for this - collection node.""" + """Collect children (items and collectors) for this collector.""" raise NotImplementedError("abstract") # TODO: This omits the style= parameter which breaks Liskov Substitution. @@ -577,6 +580,8 @@ def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[ class FSCollector(Collector): + """Base class for filesystem collectors.""" + def __init__( self, fspath: Optional[LEGACY_PATH] = None, @@ -660,7 +665,7 @@ class File(FSCollector): class Item(Node): - """A basic test invocation item. + """Base class of all test invocation items. Note that for a single function there might be multiple test invocation items. """ diff --git a/src/_pytest/python.py b/src/_pytest/python.py index ad847c8afe2..b24dc90d8ee 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -522,7 +522,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: class Module(nodes.File, PyCollector): - """Collector for test classes and functions.""" + """Collector for test classes and functions in a Python module.""" def _getobj(self): return self._importtestmodule() @@ -659,6 +659,9 @@ def _importtestmodule(self): class Package(Module): + """Collector for files and directories in a Python packages -- directories + with an `__init__.py` file.""" + def __init__( self, fspath: Optional[LEGACY_PATH], @@ -788,7 +791,7 @@ def _get_first_non_fixture_func(obj: object, names: Iterable[str]) -> Optional[o class Class(PyCollector): - """Collector for test methods.""" + """Collector for test methods (and nested classes) in a Python class.""" @classmethod def from_parent(cls, parent, *, name, obj=None, **kw): @@ -1673,7 +1676,7 @@ def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None: class Function(PyobjMixin, nodes.Item): - """An Item responsible for setting up and executing a Python test function. + """Item responsible for setting up and executing a Python test function. :param name: The full function name, including any decorations like those @@ -1830,10 +1833,8 @@ def repr_failure( # type: ignore[override] class FunctionDefinition(Function): - """ - This class is a step gap solution until we evolve to have actual function definition nodes - and manage to get rid of ``metafunc``. - """ + """This class is a stop gap solution until we evolve to have actual function + definition nodes and manage to get rid of ``metafunc``.""" def runtest(self) -> None: raise RuntimeError("function definitions are not supposed to be run as tests") From 6dfe498c7747483b0e42694f1ae68cf7386c57f6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 19:17:21 +0000 Subject: [PATCH 125/157] [7.4.x] doc: fix EncodingWarnings in examples (#11182) Co-authored-by: Ran Benita --- doc/en/example/nonpython/conftest.py | 2 +- doc/en/example/simple.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/tmp_path.rst | 4 ++-- doc/en/how-to/unittest.rst | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index dd1ebe88d7e..e969e3e2518 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -12,7 +12,7 @@ def collect(self): # We need a yaml parser, e.g. PyYAML. import yaml - raw = yaml.safe_load(self.path.open()) + raw = yaml.safe_load(self.path.open(encoding="utf-8")) for name, spec in sorted(raw.items()): yield YamlItem.from_parent(self, name=name, spec=spec) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 97a6dd9f436..32e5188b741 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -817,7 +817,7 @@ case we just write some information out to a ``failures`` file: # we only look at actual failing test calls, not setup/teardown if rep.when == "call" and rep.failed: mode = "a" if os.path.exists("failures") else "w" - with open("failures", mode) as f: + with open("failures", mode, encoding="utf-8") as f: # let's also access a fixture for the fun of it if "tmp_path" in item.fixturenames: extra = " ({})".format(item.funcargs["tmp_path"]) diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index d8517c2c8f3..a6f4962f083 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1698,7 +1698,7 @@ and declare its use in a test module via a ``usefixtures`` marker: class TestDirectoryInit: def test_cwd_starts_empty(self): assert os.listdir(os.getcwd()) == [] - with open("myfile", "w") as f: + with open("myfile", "w", encoding="utf-8") as f: f.write("hello") def test_cwd_again_starts_empty(self): diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 792933dd87e..d5573f5847d 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -24,8 +24,8 @@ created in the `base temporary directory`_. d = tmp_path / "sub" d.mkdir() p = d / "hello.txt" - p.write_text(CONTENT) - assert p.read_text() == CONTENT + p.write_text(CONTENT, encoding="utf-8") + assert p.read_text(encoding="utf-8") == CONTENT assert len(list(tmp_path.iterdir())) == 1 assert 0 diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 37caf6e9fb7..7856c1a49c0 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -207,10 +207,10 @@ creation of a per-test temporary directory: @pytest.fixture(autouse=True) def initdir(self, tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) # change to pytest-provided temporary directory - tmp_path.joinpath("samplefile.ini").write_text("# testdata") + tmp_path.joinpath("samplefile.ini").write_text("# testdata", encoding="utf-8") def test_method(self): - with open("samplefile.ini") as f: + with open("samplefile.ini", encoding="utf-8") as f: s = f.read() assert "testdata" in s From 06ff7ca13bfe7f860110a829ed48f3d427e6502c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 9 Jul 2023 15:54:59 +0000 Subject: [PATCH 126/157] [7.4.x] Clarify docs for pytest.main default behavior (#11188) Co-authored-by: antosikv <79337398+antosikv@users.noreply.github.com> --- doc/en/how-to/usage.rst | 3 ++- src/_pytest/config/__init__.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 8e2dd86736f..4ec4459a232 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -173,7 +173,8 @@ You can invoke ``pytest`` from Python code directly: this acts as if you would call "pytest" from the command line. It will not raise :class:`SystemExit` but return the :ref:`exit code ` instead. -You can pass in options and arguments: +If you don't pass it any arguments, ``main`` reads the arguments from the command line arguments of the process (:data:`sys.argv`), which may be undesirable. +You can pass in options and arguments explicitly: .. code-block:: python diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c9a4b7f63cb..45f4cf831ff 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -137,7 +137,9 @@ def main( ) -> Union[int, ExitCode]: """Perform an in-process test run. - :param args: List of command line arguments. + :param args: + List of command line arguments. If `None` or not given, defaults to reading + arguments directly from the process command line (:data:`sys.argv`). :param plugins: List of plugin objects to be auto-registered during initialization. :returns: An exit code. From 350122abb2674f98144b9267b195f3e84a032e66 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Jul 2023 18:40:56 +0000 Subject: [PATCH 127/157] [7.4.x] Remove ep2023 training (#11242) Co-authored-by: Florian Bruhin --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 50f3e9c10c3..69ca1dcfea9 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,6 @@ .. sidebar:: Next Open Trainings - - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, **July 18th** (3h), **Prague, Czech Republic / Remote** - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** From 34c73944e1d8e89a802a82a71ed75efcd1ee6700 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:47:12 +0200 Subject: [PATCH 128/157] [7.4.x] doc: update information about assertion messages (#11286) Co-authored-by: Christoph Anton Mitterer --- doc/en/how-to/assert.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 1b10c131389..d99a1ce5c97 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -54,14 +54,13 @@ operators. (See :ref:`tbreportdemo`). This allows you to use the idiomatic python constructs without boilerplate code while not losing introspection information. -However, if you specify a message with the assertion like this: +If a message is specified with the assertion like this: .. code-block:: python assert a % 2 == 0, "value was odd, should be even" -then no assertion introspection takes places at all and the message -will be simply shown in the traceback. +it is printed alongside the assertion introspection in the traceback. See :ref:`assert-details` for more information on assertion introspection. From e3fe7286f803cff00314b64ffaaedd5cfc9a6b8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:47:37 +0200 Subject: [PATCH 129/157] [7.4.x] doc: Link pytest.main to how-to guide (#11290) Co-authored-by: Florian Bruhin --- doc/en/reference/reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 9e79397f09d..767f8a8f3d3 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -82,6 +82,8 @@ pytest.exit pytest.main ~~~~~~~~~~~ +**Tutorial**: :ref:`pytest.main-usage` + .. autofunction:: pytest.main pytest.param From ba40975bb72e8b2ba749a06ccffef42638f8800a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 7 Aug 2023 12:08:56 +0200 Subject: [PATCH 130/157] ci: Use Python 3.8 to test latest pluggy Pluggy dropped Python 3.7 support. Also see 165fbbd12a74ab639d61ce1f28dfef1511a2c2e2 Fixes #11293 --- .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 cf5027223e1..eb2dfa85d26 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,17 +38,17 @@ jobs: matrix: name: [ "windows-py37", - "windows-py37-pluggy", "windows-py38", + "windows-py38-pluggy", "windows-py39", "windows-py310", "windows-py311", "windows-py312", "ubuntu-py37", - "ubuntu-py37-pluggy", "ubuntu-py37-freeze", "ubuntu-py38", + "ubuntu-py38-pluggy", "ubuntu-py39", "ubuntu-py310", "ubuntu-py311", @@ -70,15 +70,15 @@ jobs: python: "3.7" os: windows-latest tox_env: "py37-numpy" - - name: "windows-py37-pluggy" - python: "3.7" - os: windows-latest - tox_env: "py37-pluggymain-pylib-xdist" - name: "windows-py38" python: "3.8" os: windows-latest tox_env: "py38-unittestextras" use_coverage: true + - name: "windows-py38-pluggy" + python: "3.8" + os: windows-latest + tox_env: "py38-pluggymain-pylib-xdist" - name: "windows-py39" python: "3.9" os: windows-latest @@ -101,10 +101,6 @@ jobs: os: ubuntu-latest tox_env: "py37-lsof-numpy-pexpect" use_coverage: true - - name: "ubuntu-py37-pluggy" - python: "3.7" - os: ubuntu-latest - tox_env: "py37-pluggymain-pylib-xdist" - name: "ubuntu-py37-freeze" python: "3.7" os: ubuntu-latest @@ -113,6 +109,10 @@ jobs: python: "3.8" os: ubuntu-latest tox_env: "py38-xdist" + - name: "ubuntu-py38-pluggy" + python: "3.8" + os: ubuntu-latest + tox_env: "py38-pluggymain-pylib-xdist" - name: "ubuntu-py39" python: "3.9" os: ubuntu-latest From 69140717d468cf93750c3f54254ca960455bfd1a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:44:03 +0300 Subject: [PATCH 131/157] [7.4.x] Improve duplicate values documentation (#11296) Co-authored-by: Bruno Oliveira --- src/_pytest/python.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index b24dc90d8ee..5f8be5d9b9e 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1152,7 +1152,7 @@ def setmulti( arg2scope = self._arg2scope.copy() for arg, val in zip(argnames, valset): if arg in params or arg in funcargs: - raise ValueError(f"duplicate {arg!r}") + raise ValueError(f"duplicate parametrization of {arg!r}") valtype_for_arg = valtypes[arg] if valtype_for_arg == "params": params[arg] = val @@ -1243,8 +1243,9 @@ def parametrize( during the collection phase. If you need to setup expensive resources see about setting indirect to do it rather than at test setup time. - Can be called multiple times, in which case each call parametrizes all - previous parametrizations, e.g. + Can be called multiple times per test function (but only on different + argument names), in which case each call parametrizes all previous + parametrizations, e.g. :: From 7a5f2feefbbb976b1c5b4ced18e7e6725edfd3d5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 27 Aug 2023 01:15:32 +0300 Subject: [PATCH 132/157] [7.4.x] Fixes for typed pluggy (#11355) Since version 1.3 pluggy added typing, which requires some fixes to please mypy. --- doc/en/reference/reference.rst | 4 ++-- src/_pytest/config/__init__.py | 13 +++++++------ src/_pytest/helpconfig.py | 6 +++++- src/_pytest/logging.py | 2 ++ src/_pytest/pytester.py | 2 +- testing/test_pluginmanager.py | 10 ++++++++-- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 767f8a8f3d3..38b58b5c4c7 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -978,10 +978,10 @@ TestShortLogReport .. autoclass:: pytest.TestShortLogReport() :members: -_Result +Result ~~~~~~~ -Result object used within :ref:`hook wrappers `, see :py:class:`_Result in the pluggy documentation ` for more information. +Result object used within :ref:`hook wrappers `, see :py:class:`Result in the pluggy documentation ` for more information. Stash ~~~~~ diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 45f4cf831ff..dc2b9f6a160 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -444,10 +444,10 @@ def parse_hookimpl_opts(self, plugin: _PluggyPlugin, name: str): # so we avoid accessing possibly non-readable attributes # (see issue #1073). if not name.startswith("pytest_"): - return + return None # Ignore names which can not be hooks. if name == "pytest_plugins": - return + return None opts = super().parse_hookimpl_opts(plugin, name) if opts is not None: @@ -456,9 +456,9 @@ def parse_hookimpl_opts(self, plugin: _PluggyPlugin, name: str): method = getattr(plugin, name) # Consider only actual functions for hooks (#3775). if not inspect.isroutine(method): - return + return None # Collect unmarked hooks as long as they have the `pytest_' prefix. - return _get_legacy_hook_marks( + return _get_legacy_hook_marks( # type: ignore[return-value] method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper") ) @@ -467,7 +467,7 @@ def parse_hookspec_opts(self, module_or_class, name: str): if opts is None: method = getattr(module_or_class, name) if name.startswith("pytest_"): - opts = _get_legacy_hook_marks( + opts = _get_legacy_hook_marks( # type: ignore[assignment] method, "spec", ("firstresult", "historic"), @@ -1065,9 +1065,10 @@ def _ensure_unconfigure(self) -> None: fin() def get_terminal_writer(self) -> TerminalWriter: - terminalreporter: TerminalReporter = self.pluginmanager.get_plugin( + terminalreporter: Optional[TerminalReporter] = self.pluginmanager.get_plugin( "terminalreporter" ) + assert terminalreporter is not None return terminalreporter._tw def pytest_cmdline_parse( diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 430870608bd..ea16c438823 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -11,6 +11,7 @@ from _pytest.config import ExitCode from _pytest.config import PrintHelp from _pytest.config.argparsing import Parser +from _pytest.terminal import TerminalReporter class HelpAction(Action): @@ -159,7 +160,10 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: def showhelp(config: Config) -> None: import textwrap - reporter = config.pluginmanager.get_plugin("terminalreporter") + reporter: Optional[TerminalReporter] = config.pluginmanager.get_plugin( + "terminalreporter" + ) + assert reporter is not None tw = reporter._tw tw.write(config._parser.optparser.format_help()) tw.line() diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 83813466016..9f2f1c79359 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -660,6 +660,8 @@ def __init__(self, config: Config) -> None: ) if self._log_cli_enabled(): terminal_reporter = config.pluginmanager.get_plugin("terminalreporter") + # Guaranteed by `_log_cli_enabled()`. + assert terminal_reporter is not None capture_manager = config.pluginmanager.get_plugin("capturemanager") # if capturemanager plugin is disabled, live logging still works. self.log_cli_handler: Union[ diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 3df52ebe88c..cdfc2c04ae1 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -752,7 +752,7 @@ def preserve_module(name): def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder: """Create a new :class:`HookRecorder` for a :class:`PytestPluginManager`.""" - pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) + pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) # type: ignore[attr-defined] self._request.addfinalizer(reprec.finish_recording) return reprec diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index c6f518b1da2..e5773412fbf 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -242,8 +242,12 @@ def test_consider_module( mod = types.ModuleType("temp") mod.__dict__["pytest_plugins"] = ["pytest_p1", "pytest_p2"] pytestpm.consider_module(mod) - assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1" - assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2" + p1 = pytestpm.get_plugin("pytest_p1") + assert p1 is not None + assert p1.__name__ == "pytest_p1" + p2 = pytestpm.get_plugin("pytest_p2") + assert p2 is not None + assert p2.__name__ == "pytest_p2" def test_consider_module_import_module( self, pytester: Pytester, _config_for_test: Config @@ -336,6 +340,7 @@ def test_import_plugin_importname( len2 = len(pytestpm.get_plugins()) assert len1 == len2 plugin1 = pytestpm.get_plugin("pytest_hello") + assert plugin1 is not None assert plugin1.__name__.endswith("pytest_hello") plugin2 = pytestpm.get_plugin("pytest_hello") assert plugin2 is plugin1 @@ -351,6 +356,7 @@ def test_import_plugin_dotted_name( pluginname = "pkg.plug" pytestpm.import_plugin(pluginname) mod = pytestpm.get_plugin("pkg.plug") + assert mod is not None assert mod.x == 3 def test_consider_conftest_deps( From b170081788ad51a2ccf5d47205e69f98bf6f574d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 00:40:49 +0000 Subject: [PATCH 133/157] [7.4.x] Issue 11354 fixing docs for lfnf (#11364) Co-authored-by: Sean Patrick Malloy --- doc/en/how-to/cache.rst | 17 ++++++++++++----- doc/en/reference/reference.rst | 7 +++++-- src/_pytest/cacheprovider.py | 6 +++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 8554a984c72..03ab0c77780 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -176,14 +176,21 @@ with more recent files coming first. Behavior when no tests failed in the last run --------------------------------------------- -When no tests failed in the last run, or when no cached ``lastfailed`` data was -found, ``pytest`` can be configured either to run all of the tests or no tests, -using the ``--last-failed-no-failures`` option, which takes one of the following values: +The ``--lfnf/--last-failed-no-failures`` option governs the behavior of ``--last-failed``. +Determines whether to execute tests when there are no previously (known) +failures or when no cached ``lastfailed`` data was found. + +There are two options: + +* ``all``: when there are no known test failures, runs all tests (the full test suite). This is the default. +* ``none``: when there are no known test failures, just emits a message stating this and exit successfully. + +Example: .. code-block:: bash - pytest --last-failed --last-failed-no-failures all # run all tests (default behavior) - pytest --last-failed --last-failed-no-failures none # run no tests and exit + pytest --last-failed --last-failed-no-failures all # runs the full test suite (default behavior) + pytest --last-failed --last-failed-no-failures none # runs no tests and exits successfully The new config.cache object -------------------------------- diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 38b58b5c4c7..ef7e19c03d0 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1887,8 +1887,11 @@ All the command-line flags can be obtained by running ``pytest --help``:: 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} - Which tests to run with no previously (known) - failures + With ``--lf``, determines whether to execute tests when there + are no previously (known) failures or when no + cached ``lastfailed`` data was found. + ``all`` (the default) runs the full test suite again. + ``none`` just emits a message about no known failures and exits successfully. --sw, --stepwise Exit on test failure and continue from last failing test next time --sw-skip, --stepwise-skip diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 855716d8199..1ecb8650580 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -505,7 +505,11 @@ def pytest_addoption(parser: Parser) -> None: dest="last_failed_no_failures", choices=("all", "none"), default="all", - help="Which tests to run with no previously (known) failures", + help="With ``--lf``, determines whether to execute tests when there " + "are no previously (known) failures or when no " + "cached ``lastfailed`` data was found. " + "``all`` (the default) runs the full test suite again. " + "``none`` just emits a message about no known failures and exits successfully.", ) From fbcfd3a52e1c64349e143aa8b146ac1a71340c68 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 08:57:49 -0300 Subject: [PATCH 134/157] [7.4.x] Update CONTRIBUTING.rst (#11371) Co-authored-by: Sourabh Beniwal --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 791f988306f..5ccc66bf5c4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -50,7 +50,7 @@ Fix bugs -------- Look through the `GitHub issues for bugs `_. -See also the `"status: easy" issues `_ +See also the `"good first issue" issues `_ that are friendly to new contributors. :ref:`Talk ` to developers to find out how you can fix specific bugs. To indicate that you are going From 7a0a0e8b0857a7194001f4860af3fbc0968765ff Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sat, 2 Sep 2023 11:03:06 +0000 Subject: [PATCH 135/157] Prepare release version 7.4.1 --- changelog/10337.bugfix.rst | 2 -- changelog/10702.bugfix.rst | 1 - changelog/10811.bugfix.rst | 2 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.1.rst | 20 ++++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 17 +++++++++++++++++ doc/en/example/reportingdemo.rst | 20 ++++++++++---------- doc/en/getting-started.rst | 2 +- doc/en/how-to/tmp_path.rst | 4 ++-- doc/en/reference/reference.rst | 11 ++++++----- 11 files changed, 58 insertions(+), 24 deletions(-) delete mode 100644 changelog/10337.bugfix.rst delete mode 100644 changelog/10702.bugfix.rst delete mode 100644 changelog/10811.bugfix.rst create mode 100644 doc/en/announce/release-7.4.1.rst diff --git a/changelog/10337.bugfix.rst b/changelog/10337.bugfix.rst deleted file mode 100644 index 3270016f926..00000000000 --- a/changelog/10337.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed bug where fake intermediate modules generated by ``--import-mode=importlib`` would not include the -child modules as attributes of the parent modules. diff --git a/changelog/10702.bugfix.rst b/changelog/10702.bugfix.rst deleted file mode 100644 index 4008cc882ec..00000000000 --- a/changelog/10702.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. diff --git a/changelog/10811.bugfix.rst b/changelog/10811.bugfix.rst deleted file mode 100644 index aa26414e457..00000000000 --- a/changelog/10811.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules -to be imported more than once, causing problems with modules that have import side effects. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 914e763bd9e..85dfa0894fe 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.1 release-7.4.0 release-7.3.2 release-7.3.1 diff --git a/doc/en/announce/release-7.4.1.rst b/doc/en/announce/release-7.4.1.rst new file mode 100644 index 00000000000..efadcf919e8 --- /dev/null +++ b/doc/en/announce/release-7.4.1.rst @@ -0,0 +1,20 @@ +pytest-7.4.1 +======================================= + +pytest 7.4.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +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 +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 53305eecded..0d673d0426e 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:528 + cache -- .../_pytest/cacheprovider.py:532 Return a cache object that can persist state between testing sessions. cache.get(key, default) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 391721df34d..be7e7fabaef 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,23 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.1 (2023-09-02) +========================= + +Bug Fixes +--------- + +- `#10337 `_: Fixed bug where fake intermediate modules generated by ``--import-mode=importlib`` would not include the + child modules as attributes of the parent modules. + + +- `#10702 `_: Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. + + +- `#10811 `_: Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules + to be imported more than once, causing problems with modules that have import side effects. + + pytest 7.4.0 (2023-06-23) ========================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index cb59c4b42e1..d4d3d3ce202 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -554,13 +554,13 @@ Here is a nice run of several failures and how ``pytest`` presents things: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - E + where '123' = .f at 0xdeadbeef0029>() - E + and '456' = .g at 0xdeadbeef002a>() + E + where '123' = .f at 0xdeadbeef0006>() + E + and '456' = .g at 0xdeadbeef0029>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:238: 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:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -618,7 +618,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -637,7 +637,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index e295c180454..31cfa68bf38 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 7.4.0 + pytest 7.4.1 .. _`simpletest`: diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index d5573f5847d..3b49d63a5be 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -51,8 +51,8 @@ Running this would result in a passed test except for the last d = tmp_path / "sub" d.mkdir() p = d / "hello.txt" - p.write_text(CONTENT) - assert p.read_text() == CONTENT + p.write_text(CONTENT, encoding="utf-8") + assert p.read_text(encoding="utf-8") == CONTENT assert len(list(tmp_path.iterdir())) == 1 > assert 0 E assert 0 diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index ef7e19c03d0..6e11d385d12 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1887,11 +1887,12 @@ All the command-line flags can be obtained by running ``pytest --help``:: 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} - With ``--lf``, determines whether to execute tests when there - are no previously (known) failures or when no - cached ``lastfailed`` data was found. - ``all`` (the default) runs the full test suite again. - ``none`` just emits a message about no known failures and exits successfully. + With ``--lf``, determines whether to execute tests + when there are no previously (known) failures or + when no cached ``lastfailed`` data was found. + ``all`` (the default) runs the full test suite + again. ``none`` just emits a message about no known + failures and exits successfully. --sw, --stepwise Exit on test failure and continue from last failing test next time --sw-skip, --stepwise-skip From 7855a72d2c5c810a025460f135ffdd77160bb091 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Sep 2023 08:13:00 -0300 Subject: [PATCH 136/157] Improve CI workflow * Build the package only once, and test on all platforms. * Deploy is now triggered manually via an Action, which is then responsible for tagging the repository after the package has been uploaded successfully. * Drop 'docs': we nowadays rely on readthedocs preview PR builds. --- .github/workflows/deploy.yml | 33 +++++++++++++++++++++++---------- .github/workflows/test.yml | 36 ++++++++++++++++++++++-------------- RELEASING.rst | 11 ++++------- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e6b4f0ea2d7..34145271c34 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,33 +1,38 @@ name: deploy on: - push: - tags: - # These tags are protected, see: - # https://github.com/pytest-dev/pytest/settings/tag_protection - - "[0-9]+.[0-9]+.[0-9]+" - - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+" + workflow_dispatch: + inputs: + version: + description: 'Release version' + required: true + default: '1.2.3' # Set permissions at the job level. permissions: {} jobs: - build: + package: runs-on: ubuntu-latest + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }} timeout-minutes: 10 + steps: - uses: actions/checkout@v3 with: fetch-depth: 0 persist-credentials: false + - name: Build and Check Package uses: hynek/build-and-inspect-python-package@v1.5 deploy: if: github.repository == 'pytest-dev/pytest' - needs: [build] + needs: [package] runs-on: ubuntu-latest + environment: deploy timeout-minutes: 30 permissions: id-token: write @@ -37,9 +42,17 @@ jobs: with: name: Packages path: dist + - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@v1.8.5 + - name: Push tag + run: | + git config user.name "pytest bot" + git config user.email "pytestbot@gmail.com" + git tag --annotate --message=v${{ github.event.inputs.version }} v${{ github.event.inputs.version }} ${{ github.sha }} + git push origin v${{ github.event.inputs.version }} + release-notes: # todo: generate the content in the build job @@ -55,11 +68,11 @@ jobs: with: fetch-depth: 0 persist-credentials: false + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.7" - + python-version: "3.10" - name: Install tox run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eb2dfa85d26..a3c2d9ed5a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,19 @@ concurrency: permissions: {} jobs: + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false + - name: Build and Check Package + uses: hynek/build-and-inspect-python-package@v1.5 + build: + needs: [package] + runs-on: ${{ matrix.os }} timeout-minutes: 45 permissions: @@ -60,7 +72,6 @@ jobs: "macos-py310", "macos-py312", - "docs", "doctesting", "plugins", ] @@ -159,10 +170,6 @@ jobs: os: ubuntu-latest tox_env: "plugins" - - name: "docs" - python: "3.7" - os: ubuntu-latest - tox_env: "docs" - name: "doctesting" python: "3.7" os: ubuntu-latest @@ -175,6 +182,12 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: Download Package + uses: actions/download-artifact@v3 + with: + name: Packages + path: dist + - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 with: @@ -188,11 +201,13 @@ jobs: - name: Test without coverage if: "! matrix.use_coverage" - run: "tox -e ${{ matrix.tox_env }}" + shell: bash + run: tox run -e ${{ matrix.tox_env }} --installpkg `find dist/*.tar.gz` - name: Test with coverage if: "matrix.use_coverage" - run: "tox -e ${{ matrix.tox_env }}-coverage" + shell: bash + run: tox run -e ${{ matrix.tox_env }}-coverage --installpkg `find dist/*.tar.gz` - name: Generate coverage report if: "matrix.use_coverage" @@ -206,10 +221,3 @@ jobs: fail_ci_if_error: true files: ./coverage.xml verbose: true - - check-package: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5 diff --git a/RELEASING.rst b/RELEASING.rst index b018dc48932..5d49fb5d6d9 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -133,14 +133,11 @@ Releasing Both automatic and manual processes described above follow the same steps from this point onward. -#. After all tests pass and the PR has been approved, tag the release commit - in the ``release-MAJOR.MINOR.PATCH`` branch and push it. This will publish to PyPI:: +#. After all tests pass and the PR has been approved, trigger the ``deploy`` job + in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml. - git fetch upstream - git tag MAJOR.MINOR.PATCH upstream/release-MAJOR.MINOR.PATCH - git push upstream MAJOR.MINOR.PATCH - - Wait for the deploy to complete, then make sure it is `available on PyPI `_. + This job will require approval from ``pytest-dev/core``, after which it will publish to PyPI + and tag the repository. #. Merge the PR. **Make sure it's not squash-merged**, so that the tagged commit ends up in the main branch. From 0319a0d4fd9ef432a52cfeed69d32f86e6aa9b31 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Sep 2023 12:38:39 -0300 Subject: [PATCH 137/157] Checkout source code during deploy We need the checked out repository in order to push the tag. --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 34145271c34..4cda08650ad 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -37,6 +37,7 @@ jobs: permissions: id-token: write steps: + - uses: actions/checkout@v3 - name: Download Package uses: actions/download-artifact@v3 with: From 7f5d9b9df4e5e323fe3a66aeb956557710e5d277 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 3 Sep 2023 15:01:56 -0300 Subject: [PATCH 138/157] Fix user_properties not saved to XML if fixture errors during teardown (#11382) Move handling of user_properties to `finalize()`. Previously if a fixture failed during teardown, `pytest_runtest_logreport` would not be called with "teardown", resulting in the user properties not being saved on the JUnit XML file. Fixes: #11367 (cherry picked from commit 917ce9aa0102c7f0ec8fdac118058c41ffb603e6) Co-authored-by: Israel Fruchter --- AUTHORS | 2 ++ changelog/11367.bugfix.rst | 1 + src/_pytest/junitxml.py | 7 ++++--- testing/test_junitxml.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 changelog/11367.bugfix.rst diff --git a/AUTHORS b/AUTHORS index ee4ef203f0c..d914f3ba906 100644 --- a/AUTHORS +++ b/AUTHORS @@ -166,6 +166,8 @@ Ian Bicking Ian Lesperance Ilya Konstantinov Ionuț Turturică +Isaac Virshup +Israel Fruchter Itxaso Aizpurua Iwan Briquemont Jaap Broekhuizen diff --git a/changelog/11367.bugfix.rst b/changelog/11367.bugfix.rst new file mode 100644 index 00000000000..dda40db0fc9 --- /dev/null +++ b/changelog/11367.bugfix.rst @@ -0,0 +1 @@ +Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 9242d46d9df..ed259e4c41d 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -502,6 +502,10 @@ def finalize(self, report: TestReport) -> None: # Local hack to handle xdist report order. workernode = getattr(report, "node", None) reporter = self.node_reporters.pop((nodeid, workernode)) + + for propname, propvalue in report.user_properties: + reporter.add_property(propname, str(propvalue)) + if reporter is not None: reporter.finalize() @@ -599,9 +603,6 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: reporter = self._opentestcase(report) reporter.write_captured_output(report) - for propname, propvalue in report.user_properties: - reporter.add_property(propname, str(propvalue)) - self.finalize(report) report_wid = getattr(report, "worker_id", None) report_ii = getattr(report, "item_index", None) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 690830329c0..3f88c21e2b7 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1228,6 +1228,36 @@ def test_record(record_property, other): result.stdout.fnmatch_lines(["*= 1 passed in *"]) +def test_record_property_on_test_and_teardown_failure( + pytester: Pytester, run_and_parse: RunAndParse +) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def other(record_property): + record_property("bar", 1) + yield + assert 0 + + def test_record(record_property, other): + record_property("foo", "<1") + assert 0 + """ + ) + result, dom = run_and_parse() + node = dom.find_first_by_tag("testsuite") + tnodes = node.find_by_tag("testcase") + for tnode in tnodes: + psnode = tnode.find_first_by_tag("properties") + assert psnode, f"testcase didn't had expected properties:\n{tnode}" + pnodes = psnode.find_by_tag("property") + pnodes[0].assert_attr(name="bar", value="1") + pnodes[1].assert_attr(name="foo", value="<1") + result.stdout.fnmatch_lines(["*= 1 failed, 1 error *"]) + + def test_record_property_same_name( pytester: Pytester, run_and_parse: RunAndParse ) -> None: From 1de00e9830c57805ec07a0d67095822703b90bb4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 23:07:48 +0000 Subject: [PATCH 139/157] [7.4.x] Fix import_path for packages (#11395) Co-authored-by: Bruno Oliveira --- changelog/11306.bugfix.rst | 1 + src/_pytest/pathlib.py | 4 ++++ testing/test_pathlib.py | 45 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 changelog/11306.bugfix.rst diff --git a/changelog/11306.bugfix.rst b/changelog/11306.bugfix.rst new file mode 100644 index 00000000000..02e0957a9c6 --- /dev/null +++ b/changelog/11306.bugfix.rst @@ -0,0 +1 @@ +Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 14fb2e3ae2f..7cf64f03b2c 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -623,6 +623,10 @@ def module_name_from_path(path: Path, root: Path) -> str: # Use the parts for the relative path to the root path. path_parts = relative_path.parts + # Module name for packages do not contain the __init__ file. + if path_parts[-1] == "__init__": + path_parts = path_parts[:-1] + return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 3d574e85658..1ca6414375e 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -18,6 +18,7 @@ from _pytest.pathlib import get_extended_length_path_str from _pytest.pathlib import get_lock_path from _pytest.pathlib import import_path +from _pytest.pathlib import ImportMode from _pytest.pathlib import ImportPathMismatchError from _pytest.pathlib import insert_missing_modules from _pytest.pathlib import maybe_delete_a_numbered_dir @@ -585,6 +586,10 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: result = module_name_from_path(Path("/home/foo/test_foo.py"), Path("/bar")) assert result == "home.foo.test_foo" + # Importing __init__.py files should return the package as module name. + result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) + assert result == "src.app" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -615,3 +620,43 @@ def test_parent_contains_child_module_attribute( assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"] assert modules["xxx"].tests is modules["xxx.tests"] assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] + + def test_importlib_package(self, monkeypatch: MonkeyPatch, tmp_path: Path): + """ + Importing a package using --importmode=importlib should not import the + package's __init__.py file more than once (#11306). + """ + monkeypatch.chdir(tmp_path) + monkeypatch.syspath_prepend(tmp_path) + + package_name = "importlib_import_package" + tmp_path.joinpath(package_name).mkdir() + init = tmp_path.joinpath(f"{package_name}/__init__.py") + init.write_text( + dedent( + """ + from .singleton import Singleton + + instance = Singleton() + """ + ), + encoding="ascii", + ) + singleton = tmp_path.joinpath(f"{package_name}/singleton.py") + singleton.write_text( + dedent( + """ + class Singleton: + INSTANCES = [] + + def __init__(self) -> None: + self.INSTANCES.append(self) + if len(self.INSTANCES) > 1: + raise RuntimeError("Already initialized") + """ + ), + encoding="ascii", + ) + + mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) + assert len(mod.instance.INSTANCES) == 1 From de69883e3a6a923c9eceb28cedf8e9660bd58a51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:02:29 +0000 Subject: [PATCH 140/157] [7.4.x] improve plugin list disclaimer (#11398) Co-authored-by: Stefaan Lippens --- AUTHORS | 1 + changelog/11391.doc.rst | 1 + doc/en/reference/plugin_list.rst | 22 +++++++++++++++++----- scripts/update-plugin-list.py | 22 +++++++++++++++++----- 4 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 changelog/11391.doc.rst diff --git a/AUTHORS b/AUTHORS index d914f3ba906..74043fcfb6c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -341,6 +341,7 @@ Simon Holesch Simon Kerr Skylar Downes Srinivas Reddy Thatiparthy +Stefaan Lippens Stefan Farmbauer Stefan Scherfke Stefan Zimmermann diff --git a/changelog/11391.doc.rst b/changelog/11391.doc.rst new file mode 100644 index 00000000000..fff324af18d --- /dev/null +++ b/changelog/11391.doc.rst @@ -0,0 +1 @@ +Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c882130b03e..42b6a9a8f29 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -1,14 +1,26 @@ .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code `_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script `_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index ea7e7986e15..2efe04165c2 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -13,14 +13,26 @@ FILE_HEAD = r""" .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code `_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script `_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. From 79c2012d4090bbe0cd0910e1616dc19ca75aea86 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:50:00 +0000 Subject: [PATCH 141/157] [7.4.x] doc: Remove done training (#11400) Co-authored-by: Florian Bruhin --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 69ca1dcfea9..bdee8b5dbd9 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,6 @@ .. sidebar:: Next Open Trainings - - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** Also see :doc:`previous talks and blogposts `. From 6e49a74089540196ae2b2bf8267a530ad9957f3e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:33:12 +0000 Subject: [PATCH 142/157] [7.4.x] Fix doctest collection of `functools.cached_property` objects. (#11403) Co-authored-by: Ronny Pfannschmidt --- AUTHORS | 1 + changelog/11237.bugfix.rst | 1 + src/_pytest/doctest.py | 20 ++++++++++++++++++++ testing/test_doctest.py | 21 +++++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 changelog/11237.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 74043fcfb6c..e8456d92b31 100644 --- a/AUTHORS +++ b/AUTHORS @@ -374,6 +374,7 @@ Tony Narlock Tor Colvin Trevor Bekolay Tyler Goodlet +Tyler Smart Tzu-ping Chung Vasily Kuznetsov Victor Maryama diff --git a/changelog/11237.bugfix.rst b/changelog/11237.bugfix.rst new file mode 100644 index 00000000000..d054fc18d1c --- /dev/null +++ b/changelog/11237.bugfix.rst @@ -0,0 +1 @@ +Fix doctest collection of `functools.cached_property` objects. diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 455ad62cc9c..ca41a98ea9c 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,5 +1,6 @@ """Discover and run doctests in modules and test files.""" import bdb +import functools import inspect import os import platform @@ -536,6 +537,25 @@ def _find( tests, obj, name, module, source_lines, globs, seen ) + if sys.version_info < (3, 13): + + def _from_module(self, module, object): + """`cached_property` objects are never considered a part + of the 'current module'. As such they are skipped by doctest. + Here we override `_from_module` to check the underlying + function instead. https://github.com/python/cpython/issues/107995 + """ + if hasattr(functools, "cached_property") and isinstance( + object, functools.cached_property + ): + object = object.func + + # Type ignored because this is a private function. + return super()._from_module(module, object) # type: ignore[misc] + + else: # pragma: no cover + pass + if self.path.name == "conftest.py": module = self.config.pluginmanager._importconftest( self.path, diff --git a/testing/test_doctest.py b/testing/test_doctest.py index dfe569987ca..665bdb73b5d 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -482,6 +482,27 @@ def test_doctestmodule(self, pytester: Pytester): reprec = pytester.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) + @pytest.mark.skipif( + sys.version_info[:2] <= (3, 7), reason="Only Python 3.7 or less" + ) + def test_doctest_cached_property(self, pytester: Pytester): + p = pytester.makepyfile( + """ + import functools + + class Foo: + @functools.cached_property + def foo(self): + ''' + >>> assert False, "Tacos!" + ''' + ... + """ + ) + result = pytester.runpytest(p, "--doctest-modules") + result.assert_outcomes(failed=1) + assert "Tacos!" in result.stdout.str() + def test_doctestmodule_external_and_issue116(self, pytester: Pytester): p = pytester.mkpydir("hello") p.joinpath("__init__.py").write_text( From 884b911a9cbf3c97689b473ae7f732fc72e06eea Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Sep 2023 12:49:25 -0300 Subject: [PATCH 143/157] Fix crash when passing a very long cmdline argument (#11404) Fixes #11394 (cherry picked from commit 28ccf476b91be32ffda303f0d7a8b57e475b465b) --- changelog/11394.bugfix.rst | 1 + src/_pytest/main.py | 3 ++- src/_pytest/pathlib.py | 11 +++++++++++ testing/test_main.py | 31 +++++++++++++++++++++++++++++++ testing/test_pathlib.py | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 changelog/11394.bugfix.rst diff --git a/changelog/11394.bugfix.rst b/changelog/11394.bugfix.rst new file mode 100644 index 00000000000..aa89c81b01f --- /dev/null +++ b/changelog/11394.bugfix.rst @@ -0,0 +1 @@ +Fixed crash when parsing long command line arguments that might be interpreted as files. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 803b95a2033..ea89a63fa1b 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -36,6 +36,7 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath from _pytest.pathlib import fnmatch_ex +from _pytest.pathlib import safe_exists from _pytest.pathlib import visit from _pytest.reports import CollectReport from _pytest.reports import TestReport @@ -895,7 +896,7 @@ def resolve_collection_argument( strpath = search_pypath(strpath) fspath = invocation_path / strpath fspath = absolutepath(fspath) - if not fspath.exists(): + if not safe_exists(fspath): msg = ( "module or package not found: {arg} (missing __init__.py?)" if as_pypath diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7cf64f03b2c..b5c2d86452f 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,5 +1,6 @@ import atexit import contextlib +import errno import fnmatch import importlib.util import itertools @@ -791,3 +792,13 @@ def copytree(source: Path, target: Path) -> None: shutil.copyfile(x, newx) elif x.is_dir(): newx.mkdir(exist_ok=True) + + +def safe_exists(p: Path) -> bool: + """Like Path.exists(), but account for input arguments that might be too long (#11394).""" + try: + return p.exists() + except OSError as e: + if e.errno == errno.ENAMETOOLONG: + return False + raise diff --git a/testing/test_main.py b/testing/test_main.py index 71597626790..3c8998c1a35 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -262,3 +262,34 @@ def test(fix): "* 1 passed in *", ] ) + + +def test_very_long_cmdline_arg(pytester: Pytester) -> None: + """ + Regression test for #11394. + + Note: we could not manage to actually reproduce the error with this code, we suspect + GitHub runners are configured to support very long paths, however decided to leave + the test in place in case this ever regresses in the future. + """ + pytester.makeconftest( + """ + import pytest + + def pytest_addoption(parser): + parser.addoption("--long-list", dest="long_list", action="store", default="all", help="List of things") + + @pytest.fixture(scope="module") + def specified_feeds(request): + list_string = request.config.getoption("--long-list") + return list_string.split(',') + """ + ) + pytester.makepyfile( + """ + def test_foo(specified_feeds): + assert len(specified_feeds) == 100_000 + """ + ) + result = pytester.runpytest("--long-list", ",".join(["helloworld"] * 100_000)) + result.stdout.fnmatch_lines("* 1 passed *") diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 1ca6414375e..8a9659aabd9 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,3 +1,4 @@ +import errno import os.path import pickle import sys @@ -24,6 +25,7 @@ from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import module_name_from_path from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit from _pytest.tmpdir import TempPathFactory @@ -660,3 +662,33 @@ def __init__(self) -> None: mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) assert len(mod.instance.INSTANCES) == 1 + + +def test_safe_exists(tmp_path: Path) -> None: + d = tmp_path.joinpath("some_dir") + d.mkdir() + assert safe_exists(d) is True + + f = tmp_path.joinpath("some_file") + f.touch() + assert safe_exists(f) is True + + # Use unittest.mock() as a context manager to have a very narrow + # patch lifetime. + p = tmp_path.joinpath("some long filename" * 100) + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=OSError(errno.ENAMETOOLONG, "name too long"), + ): + assert safe_exists(p) is False + + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=OSError(errno.EIO, "another kind of error"), + ): + with pytest.raises(OSError): + _ = safe_exists(p) From 63b0c6f75f218b400a5a42305f9fa3830448f7e8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Sep 2023 13:15:11 -0300 Subject: [PATCH 144/157] Use _pytest.pathlib.safe_exists in get_dirs_from_args Related to #11394 --- src/_pytest/config/__init__.py | 9 +++------ src/_pytest/config/findpaths.py | 9 +-------- src/_pytest/pathlib.py | 9 ++++----- testing/test_pathlib.py | 5 ++--- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index dc2b9f6a160..e3990d175df 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -57,6 +57,7 @@ from _pytest.pathlib import import_path from _pytest.pathlib import ImportMode from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.stash import Stash from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import warn_explicit_for @@ -557,12 +558,8 @@ def _set_initial_conftests( anchor = absolutepath(current / path) # Ensure we do not break if what appears to be an anchor - # is in fact a very long option (#10169). - try: - anchor_exists = anchor.exists() - except OSError: # pragma: no cover - anchor_exists = False - if anchor_exists: + # is in fact a very long option (#10169, #11394). + if safe_exists(anchor): self._try_load_conftest(anchor, importmode, rootpath) foundanchor = True if not foundanchor: diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 234b9e12906..02674ffae3b 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -16,6 +16,7 @@ from _pytest.outcomes import fail from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath +from _pytest.pathlib import safe_exists if TYPE_CHECKING: from . import Config @@ -151,14 +152,6 @@ def get_dir_from_path(path: Path) -> Path: return path return path.parent - def safe_exists(path: Path) -> bool: - # This can throw on paths that contain characters unrepresentable at the OS level, - # or with invalid syntax on Windows (https://bugs.python.org/issue35306) - try: - return path.exists() - except OSError: - return False - # These look like paths but may not exist possible_paths = ( absolutepath(get_file_part_from_node_id(arg)) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index b5c2d86452f..5c765c68348 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,6 +1,5 @@ import atexit import contextlib -import errno import fnmatch import importlib.util import itertools @@ -798,7 +797,7 @@ def safe_exists(p: Path) -> bool: """Like Path.exists(), but account for input arguments that might be too long (#11394).""" try: return p.exists() - except OSError as e: - if e.errno == errno.ENAMETOOLONG: - return False - raise + except (ValueError, OSError): + # ValueError: stat: path too long for Windows + # OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect + return False diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 8a9659aabd9..678fd27feac 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -688,7 +688,6 @@ def test_safe_exists(tmp_path: Path) -> None: Path, "exists", autospec=True, - side_effect=OSError(errno.EIO, "another kind of error"), + side_effect=ValueError("name too long"), ): - with pytest.raises(OSError): - _ = safe_exists(p) + assert safe_exists(p) is False From 45f34dfb8d813b00c7d8060a3ea75f7b4bc5cd7d Mon Sep 17 00:00:00 2001 From: pytest bot Date: Thu, 7 Sep 2023 17:21:49 +0000 Subject: [PATCH 145/157] Prepare release version 7.4.2 --- changelog/11237.bugfix.rst | 1 - changelog/11306.bugfix.rst | 1 - changelog/11367.bugfix.rst | 1 - changelog/11391.doc.rst | 1 - changelog/11394.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.2.rst | 18 ++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 25 +++++++++++++++++++++++++ doc/en/example/reportingdemo.rst | 20 ++++++++++---------- doc/en/getting-started.rst | 2 +- 11 files changed, 56 insertions(+), 17 deletions(-) delete mode 100644 changelog/11237.bugfix.rst delete mode 100644 changelog/11306.bugfix.rst delete mode 100644 changelog/11367.bugfix.rst delete mode 100644 changelog/11391.doc.rst delete mode 100644 changelog/11394.bugfix.rst create mode 100644 doc/en/announce/release-7.4.2.rst diff --git a/changelog/11237.bugfix.rst b/changelog/11237.bugfix.rst deleted file mode 100644 index d054fc18d1c..00000000000 --- a/changelog/11237.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix doctest collection of `functools.cached_property` objects. diff --git a/changelog/11306.bugfix.rst b/changelog/11306.bugfix.rst deleted file mode 100644 index 02e0957a9c6..00000000000 --- a/changelog/11306.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. diff --git a/changelog/11367.bugfix.rst b/changelog/11367.bugfix.rst deleted file mode 100644 index dda40db0fc9..00000000000 --- a/changelog/11367.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. diff --git a/changelog/11391.doc.rst b/changelog/11391.doc.rst deleted file mode 100644 index fff324af18d..00000000000 --- a/changelog/11391.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. diff --git a/changelog/11394.bugfix.rst b/changelog/11394.bugfix.rst deleted file mode 100644 index aa89c81b01f..00000000000 --- a/changelog/11394.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed crash when parsing long command line arguments that might be interpreted as files. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 85dfa0894fe..39fdfc13776 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.2 release-7.4.1 release-7.4.0 release-7.3.2 diff --git a/doc/en/announce/release-7.4.2.rst b/doc/en/announce/release-7.4.2.rst new file mode 100644 index 00000000000..22191e7b4f9 --- /dev/null +++ b/doc/en/announce/release-7.4.2.rst @@ -0,0 +1,18 @@ +pytest-7.4.2 +======================================= + +pytest 7.4.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +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 + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 0d673d0426e..405289444a8 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -105,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:737 + doctest_namespace [session scope] -- .../_pytest/doctest.py:757 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index be7e7fabaef..ecfeeb662b6 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,31 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.2 (2023-09-07) +========================= + +Bug Fixes +--------- + +- `#11237 `_: Fix doctest collection of `functools.cached_property` objects. + + +- `#11306 `_: Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. + + +- `#11367 `_: Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. + + +- `#11394 `_: Fixed crash when parsing long command line arguments that might be interpreted as files. + + + +Improved Documentation +---------------------- + +- `#11391 `_: Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. + + pytest 7.4.1 (2023-09-02) ========================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index d4d3d3ce202..cb59c4b42e1 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -554,13 +554,13 @@ Here is a nice run of several failures and how ``pytest`` presents things: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - E + where '123' = .f at 0xdeadbeef0006>() - E + and '456' = .g at 0xdeadbeef0029>() + E + where '123' = .f at 0xdeadbeef0029>() + E + and '456' = .g at 0xdeadbeef002a>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:238: 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:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -618,7 +618,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -637,7 +637,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 31cfa68bf38..e426e0c5072 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 7.4.1 + pytest 7.4.2 .. _`simpletest`: From c39bdf6190a80d522885808339cc6e3a0920ebb8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 8 Sep 2023 08:42:55 -0300 Subject: [PATCH 146/157] Adjustments to the release process (#11410) (#11415) As discussed in #11408: * Improve documentation for the release process. * Fix the description for the PRs created by the `prepare release pr` workflow. * Fix pushing tag in the `deploy` workflow. (cherry picked from commit e5c81fa41aa437261009d2dcbed5f05bb2b86647) --- .github/workflows/deploy.yml | 2 ++ RELEASING.rst | 3 ++- scripts/prepare-release-pr.py | 12 +++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4cda08650ad..7340e13664c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -36,8 +36,10 @@ jobs: timeout-minutes: 30 permissions: id-token: write + contents: write steps: - uses: actions/checkout@v3 + - name: Download Package uses: actions/download-artifact@v3 with: diff --git a/RELEASING.rst b/RELEASING.rst index 5d49fb5d6d9..08004a84c00 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -134,7 +134,8 @@ Releasing Both automatic and manual processes described above follow the same steps from this point onward. #. After all tests pass and the PR has been approved, trigger the ``deploy`` job - in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml. + in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml, using the ``release-MAJOR.MINOR.PATCH`` branch + as source. This job will require approval from ``pytest-dev/core``, after which it will publish to PyPI and tag the repository. diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 7a80de7edaa..a0e5e4d7f37 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -31,10 +31,16 @@ class InvalidFeatureRelease(Exception): SLUG = "pytest-dev/pytest" PR_BODY = """\ -Created automatically from manual trigger. +Created by the [prepare release pr](https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml) +workflow. -Once all builds pass and it has been **approved** by one or more maintainers, the build -can be released by pushing a tag `{version}` to this repository. +Once all builds pass and it has been **approved** by one or more maintainers, +start the [deploy](https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml) workflow, using these parameters: + +* `Use workflow from`: `release-{version}`. +* `Release version`: `{version}`. + +After the `deploy` workflow has been approved by a core maintainer, the package will be uploaded to PyPI automatically. """ From 5341b9cd67dad64d1d96dd0851861ff5f7f874dc Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:09:31 +0200 Subject: [PATCH 147/157] Fix assert rewriting with assignment expressions (#11414) Fixes #11239 (cherry picked from commit 7259e8db9844f6f973c1d0c0ce46cc68c8248abb) --- AUTHORS | 1 + changelog/11239.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 54 +++++++++++++++++++++++--------- testing/test_assertrewrite.py | 21 +++++++++++++ 4 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 changelog/11239.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e8456d92b31..6d860575f37 100644 --- a/AUTHORS +++ b/AUTHORS @@ -231,6 +231,7 @@ Maho Maik Figura Mandeep Bhutani Manuel Krebber +Marc Mueller Marc Schlaich Marcelo Duarte Trevisani Marcin Bachry diff --git a/changelog/11239.bugfix.rst b/changelog/11239.bugfix.rst new file mode 100644 index 00000000000..a486224cdda --- /dev/null +++ b/changelog/11239.bugfix.rst @@ -0,0 +1 @@ +Fixed ``:=`` in asserts impacting unrelated test cases. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ab83fee32b2..fd23552973e 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -13,6 +13,7 @@ import sys import tokenize import types +from collections import defaultdict from pathlib import Path from pathlib import PurePath from typing import Callable @@ -56,6 +57,10 @@ astNum = ast.Num +class Sentinel: + pass + + assertstate_key = StashKey["AssertionState"]() # pytest caches rewritten pycs in pycache dirs @@ -63,6 +68,9 @@ PYC_EXT = ".py" + (__debug__ and "c" or "o") PYC_TAIL = "." + PYTEST_TAG + PYC_EXT +# Special marker that denotes we have just left a scope definition +_SCOPE_END_MARKER = Sentinel() + class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader): """PEP302/PEP451 import hook which rewrites asserts.""" @@ -645,6 +653,8 @@ class AssertionRewriter(ast.NodeVisitor): .push_format_context() and .pop_format_context() which allows to build another %-formatted string while already building one. + :scope: A tuple containing the current scope used for variables_overwrite. + :variables_overwrite: A dict filled with references to variables that change value within an assert. This happens when a variable is reassigned with the walrus operator @@ -666,7 +676,10 @@ def __init__( else: self.enable_assertion_pass_hook = False self.source = source - self.variables_overwrite: Dict[str, str] = {} + self.scope: tuple[ast.AST, ...] = () + self.variables_overwrite: defaultdict[ + tuple[ast.AST, ...], Dict[str, str] + ] = defaultdict(dict) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -732,9 +745,17 @@ def run(self, mod: ast.Module) -> None: mod.body[pos:pos] = imports # Collect asserts. - nodes: List[ast.AST] = [mod] + self.scope = (mod,) + nodes: List[Union[ast.AST, Sentinel]] = [mod] while nodes: node = nodes.pop() + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)): + self.scope = tuple((*self.scope, node)) + nodes.append(_SCOPE_END_MARKER) + if node == _SCOPE_END_MARKER: + self.scope = self.scope[:-1] + continue + assert isinstance(node, ast.AST) for name, field in ast.iter_fields(node): if isinstance(field, list): new: List[ast.AST] = [] @@ -1005,7 +1026,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: ] ): pytest_temp = self.variable() - self.variables_overwrite[ + self.variables_overwrite[self.scope][ v.left.target.id ] = v.left # type:ignore[assignment] v.left.target.id = pytest_temp @@ -1048,17 +1069,20 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: new_args = [] new_kwargs = [] for arg in call.args: - if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite: - arg = self.variables_overwrite[arg.id] # type:ignore[assignment] + if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite.get( + self.scope, {} + ): + arg = self.variables_overwrite[self.scope][ + arg.id + ] # type:ignore[assignment] res, expl = self.visit(arg) arg_expls.append(expl) new_args.append(res) for keyword in call.keywords: - if ( - isinstance(keyword.value, ast.Name) - and keyword.value.id in self.variables_overwrite - ): - keyword.value = self.variables_overwrite[ + if isinstance( + keyword.value, ast.Name + ) and keyword.value.id in self.variables_overwrite.get(self.scope, {}): + keyword.value = self.variables_overwrite[self.scope][ keyword.value.id ] # type:ignore[assignment] res, expl = self.visit(keyword.value) @@ -1094,12 +1118,14 @@ def visit_Attribute(self, attr: ast.Attribute) -> Tuple[ast.Name, str]: def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: self.push_format_context() # We first check if we have overwritten a variable in the previous assert - if isinstance(comp.left, ast.Name) and comp.left.id in self.variables_overwrite: - comp.left = self.variables_overwrite[ + if isinstance( + comp.left, ast.Name + ) and comp.left.id in self.variables_overwrite.get(self.scope, {}): + comp.left = self.variables_overwrite[self.scope][ comp.left.id ] # type:ignore[assignment] if isinstance(comp.left, namedExpr): - self.variables_overwrite[ + self.variables_overwrite[self.scope][ comp.left.target.id ] = comp.left # type:ignore[assignment] left_res, left_expl = self.visit(comp.left) @@ -1119,7 +1145,7 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: and next_operand.target.id == left_res.id ): next_operand.target.id = self.variable() - self.variables_overwrite[ + self.variables_overwrite[self.scope][ left_res.id ] = next_operand # type:ignore[assignment] next_res, next_expl = self.visit(next_operand) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 778f843e6cf..63353438c95 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1531,6 +1531,27 @@ def test_gt(): result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"]) +class TestIssue11239: + def test_assertion_walrus_different_test_cases(self, pytester: Pytester) -> None: + """Regression for (#11239) + + Walrus operator rewriting would leak to separate test cases if they used the same variables. + """ + pytester.makepyfile( + """ + def test_1(): + state = {"x": 2}.get("x") + assert state is not None + + def test_2(): + db = {"x": 2} + assert (state := db.get("x")) is not None + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + @pytest.mark.skipif( sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems" ) From 721a0881fb99c8f749701d1301cf19a948a9554f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 9 Sep 2023 09:38:10 -0300 Subject: [PATCH 148/157] Skip test_assertion_walrus_different_test_cases on Python 3.7 --- testing/test_assertrewrite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 63353438c95..fbf2854953f 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1532,6 +1532,7 @@ def test_gt(): class TestIssue11239: + @pytest.mark.skipif(sys.version_info[:2] <= (3, 7), reason="Only Python 3.8+") def test_assertion_walrus_different_test_cases(self, pytester: Pytester) -> None: """Regression for (#11239) From d849a3ed64c6da63a0e3713892a7bfefdd56acaf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 13:02:31 +0000 Subject: [PATCH 149/157] [7.4.x] fix: closes #11343's [attr-defined] type errors (#11421) Co-authored-by: Warren Markham --- src/_pytest/compat.py | 25 +++++++++++++++++-------- testing/test_parseopt.py | 3 ++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 352211de8aa..1d0add7363e 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -380,15 +380,24 @@ def __get__(self, instance, owner=None): def get_user_id() -> int | None: - """Return the current user id, or None if we cannot get it reliably on the current platform.""" - # win32 does not have a getuid() function. - # On Emscripten, getuid() is a stub that always returns 0. - if sys.platform in ("win32", "emscripten"): + """Return the current process's real user id or None if it could not be + determined. + + :return: The user id or None if it could not be determined. + """ + # mypy follows the version and platform checking expectation of PEP 484: + # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks + # Containment checks are too complex for mypy v1.5.0 and cause failure. + if sys.platform == "win32" or sys.platform == "emscripten": + # win32 does not have a getuid() function. + # Emscripten has a return 0 stub. return None - # getuid shouldn't fail, but cpython defines such a case. - # Let's hope for the best. - uid = os.getuid() - return uid if uid != -1 else None + else: + # On other platforms, a return value of -1 is assumed to indicate that + # the current process's real user id could not be determined. + ERROR = -1 + uid = os.getuid() + return uid if uid != ERROR else None # Perform exhaustiveness checking. diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 1899abe153f..b6df035aacf 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -291,7 +291,8 @@ def test_multiple_metavar_help(self, parser: parseopt.Parser) -> None: def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: try: - encoding = locale.getencoding() # New in Python 3.11, ignores utf-8 mode + # New in Python 3.11, ignores utf-8 mode + encoding = locale.getencoding() # type: ignore[attr-defined] except AttributeError: encoding = locale.getpreferredencoding(False) try: From 1944dc06d39404ae9869b544dc2e2b482bf472e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:27:53 +0000 Subject: [PATCH 150/157] [7.4.x] Fix --import-mode=importlib when root contains `__init__.py` file (#11426) Co-authored-by: Bruno Oliveira --- src/_pytest/pathlib.py | 5 +++-- testing/test_pathlib.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 5c765c68348..c2f8535f5f5 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -623,8 +623,9 @@ def module_name_from_path(path: Path, root: Path) -> str: # Use the parts for the relative path to the root path. path_parts = relative_path.parts - # Module name for packages do not contain the __init__ file. - if path_parts[-1] == "__init__": + # Module name for packages do not contain the __init__ file, unless + # the `__init__.py` file is at the root. + if len(path_parts) >= 2 and path_parts[-1] == "__init__": path_parts = path_parts[:-1] return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 678fd27feac..5ae0bcdde09 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -28,6 +28,7 @@ from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit +from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory @@ -592,6 +593,10 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) assert result == "src.app" + # Unless __init__.py file is at the root, in which case we cannot have an empty module name. + result = module_name_from_path(tmp_path / "__init__.py", tmp_path) + assert result == "__init__" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -663,6 +668,22 @@ def __init__(self) -> None: mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) assert len(mod.instance.INSTANCES) == 1 + def test_importlib_root_is_package(self, pytester: Pytester) -> None: + """ + Regression for importing a `__init__`.py file that is at the root + (#11417). + """ + pytester.makepyfile(__init__="") + pytester.makepyfile( + """ + def test_my_test(): + assert True + """ + ) + + result = pytester.runpytest("--import-mode=importlib") + result.stdout.fnmatch_lines("* 1 passed *") + def test_safe_exists(tmp_path: Path) -> None: d = tmp_path.joinpath("some_dir") From f8bb8572fed8627946bfc82819d24b138d587257 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 11 Sep 2023 09:48:22 -0300 Subject: [PATCH 151/157] Force terminal width when running tests (#11425) (#11432) Related to #11423 (cherry picked from commit 241f2a890e3fb3f83eac807de0b4ad00510c7f65) --- testing/conftest.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/testing/conftest.py b/testing/conftest.py index 8e77fcae5ab..2a3ce5203d9 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -21,6 +21,15 @@ def restore_tracing(): sys.settrace(orig_trace) +@pytest.fixture(autouse=True) +def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None: + """ + Force terminal width to 80: some tests check the formatting of --help, which is sensible + to terminal width. + """ + monkeypatch.setenv("COLUMNS", "80") + + @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_collection_modifyitems(items): """Prefer faster tests. From 21fe071d797612468fa18dd0ae4d6dbf49846b6d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:41:01 +0000 Subject: [PATCH 152/157] [7.4.x] fix for ValueError raised in faulthandler teardown code (#11455) Co-authored-by: Simon Blanchard --- AUTHORS | 1 + changelog/11439.bugfix.rst | 1 + src/_pytest/faulthandler.py | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog/11439.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 6d860575f37..be1e7863860 100644 --- a/AUTHORS +++ b/AUTHORS @@ -337,6 +337,7 @@ Serhii Mozghovyi Seth Junot Shantanu Jain Shubham Adep +Simon Blanchard Simon Gomizelj Simon Holesch Simon Kerr diff --git a/changelog/11439.bugfix.rst b/changelog/11439.bugfix.rst new file mode 100644 index 00000000000..b5104b1bcab --- /dev/null +++ b/changelog/11439.bugfix.rst @@ -0,0 +1 @@ +Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index af879aa44cf..36040bffffc 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -1,4 +1,3 @@ -import io import os import sys from typing import Generator @@ -51,7 +50,7 @@ def get_stderr_fileno() -> int: if fileno == -1: raise AttributeError() return fileno - except (AttributeError, io.UnsupportedOperation): + except (AttributeError, ValueError): # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file. # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors # This is potentially dangerous, but the best we can do. From a5178273183ddbda0ef4e4c6aa2b92aab086776b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:23:18 +0000 Subject: [PATCH 153/157] [7.4.x] Configure ReadTheDocs to fail on warnings (#11540) Co-authored-by: Bruno Oliveira --- .readthedocs.yml | 4 ++++ doc/en/reference/customize.rst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index b506c5f4039..266d4e07aea 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,6 +9,10 @@ python: path: . - requirements: doc/en/requirements.txt +sphinx: + configuration: doc/en/conf.py + fail_on_warning: true + build: os: ubuntu-20.04 tools: diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index b794d646b8e..24c0ed21752 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -90,7 +90,7 @@ and can also be used to hold pytest configuration if they have a ``[pytest]`` se setup.cfg ~~~~~~~~~ -``setup.cfg`` files are general purpose configuration files, used originally by :doc:`distutils `, and can also be used to hold pytest configuration +``setup.cfg`` files are general purpose configuration files, used originally by ``distutils`` (now deprecated) and `setuptools `__, and can also be used to hold pytest configuration if they have a ``[tool:pytest]`` section. .. code-block:: ini From 5dc77253d439038ac64c55a5a48692ac3a53db2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:28:04 +0000 Subject: [PATCH 154/157] [7.4.x] Ensure logging tests always cleanup after themselves (#11541) Co-authored-by: Bruno Oliveira --- testing/logging/test_fixture.py | 56 +++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 8eaa2de96a8..753cf5fcd03 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -1,5 +1,7 @@ # mypy: disable-error-code="attr-defined" +# mypy: disallow-untyped-defs import logging +from typing import Iterator import pytest from _pytest.logging import caplog_records_key @@ -9,8 +11,8 @@ sublogger = logging.getLogger(__name__ + ".baz") -@pytest.fixture -def cleanup_disabled_logging(): +@pytest.fixture(autouse=True) +def cleanup_disabled_logging() -> Iterator[None]: """Simple fixture that ensures that a test doesn't disable logging. This is necessary because ``logging.disable()`` is global, so a test disabling logging @@ -27,7 +29,7 @@ def test_fixture_help(pytester: Pytester) -> None: result.stdout.fnmatch_lines(["*caplog*"]) -def test_change_level(caplog): +def test_change_level(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.debug("handler DEBUG level") logger.info("handler INFO level") @@ -42,7 +44,7 @@ def test_change_level(caplog): assert "CRITICAL" in caplog.text -def test_change_level_logging_disabled(caplog, cleanup_disabled_logging): +def test_change_level_logging_disabled(caplog: pytest.LogCaptureFixture) -> None: logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL caplog.set_level(logging.WARNING) @@ -85,9 +87,7 @@ def test2(caplog): result.stdout.no_fnmatch_line("*log from test2*") -def test_change_disabled_level_undo( - pytester: Pytester, cleanup_disabled_logging -) -> None: +def test_change_disabled_level_undo(pytester: Pytester) -> None: """Ensure that '_force_enable_logging' in 'set_level' is undone after the end of the test. Tests the logging output themselves (affected by disabled logging level). @@ -144,7 +144,7 @@ def test3(caplog): result.assert_outcomes(passed=3) -def test_with_statement(caplog): +def test_with_statement(caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.INFO): logger.debug("handler DEBUG level") logger.info("handler INFO level") @@ -159,7 +159,7 @@ def test_with_statement(caplog): assert "CRITICAL" in caplog.text -def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): +def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None: logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL with caplog.at_level(logging.WARNING): @@ -198,8 +198,8 @@ def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): ], ) def test_force_enable_logging_level_string( - caplog, cleanup_disabled_logging, level_str, expected_disable_level -): + caplog: pytest.LogCaptureFixture, level_str: str, expected_disable_level: int +) -> None: """Test _force_enable_logging using a level string. ``expected_disable_level`` is one level below ``level_str`` because the disabled log level @@ -218,7 +218,7 @@ def test_force_enable_logging_level_string( assert test_logger.manager.disable == expected_disable_level -def test_log_access(caplog): +def test_log_access(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") assert caplog.records[0].levelname == "INFO" @@ -226,7 +226,7 @@ def test_log_access(caplog): assert "boo arg" in caplog.text -def test_messages(caplog): +def test_messages(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") logger.info("bar %s\nbaz %s", "arg1", "arg2") @@ -247,14 +247,14 @@ def test_messages(caplog): assert "Exception" not in caplog.messages[-1] -def test_record_tuples(caplog): +def test_record_tuples(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") assert caplog.record_tuples == [(__name__, logging.INFO, "boo arg")] -def test_unicode(caplog): +def test_unicode(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("bū") assert caplog.records[0].levelname == "INFO" @@ -262,7 +262,7 @@ def test_unicode(caplog): assert "bū" in caplog.text -def test_clear(caplog): +def test_clear(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("bū") assert len(caplog.records) @@ -273,7 +273,9 @@ def test_clear(caplog): @pytest.fixture -def logging_during_setup_and_teardown(caplog): +def logging_during_setup_and_teardown( + caplog: pytest.LogCaptureFixture, +) -> Iterator[None]: caplog.set_level("INFO") logger.info("a_setup_log") yield @@ -281,7 +283,9 @@ def logging_during_setup_and_teardown(caplog): assert [x.message for x in caplog.get_records("teardown")] == ["a_teardown_log"] -def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown): +def test_caplog_captures_for_all_stages( + caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None +) -> None: assert not caplog.records assert not caplog.get_records("call") logger.info("a_call_log") @@ -290,25 +294,31 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] # This reaches into private API, don't use this type of thing in real tests! - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} -def test_clear_for_call_stage(caplog, logging_during_setup_and_teardown): +def test_clear_for_call_stage( + caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None +) -> None: logger.info("a_call_log") assert [x.message for x in caplog.get_records("call")] == ["a_call_log"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} caplog.clear() assert caplog.get_records("call") == [] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} logging.info("a_call_log_after_clear") assert [x.message for x in caplog.get_records("call")] == ["a_call_log_after_clear"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} def test_ini_controls_global_log_level(pytester: Pytester) -> None: From 44ad1c9811d2ebf540e601ea66b9bebf8ea82969 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:04:13 +0000 Subject: [PATCH 155/157] [7.4.x] fix #10447 - consider marks in reverse mro order to give base classes priority (#11545) Co-authored-by: Ronny Pfannschmidt --- changelog/10447.bugfix.rst | 2 ++ src/_pytest/mark/structures.py | 4 +++- testing/test_mark.py | 37 +++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 changelog/10447.bugfix.rst diff --git a/changelog/10447.bugfix.rst b/changelog/10447.bugfix.rst new file mode 100644 index 00000000000..fff94b28fb5 --- /dev/null +++ b/changelog/10447.bugfix.rst @@ -0,0 +1,2 @@ +markers are now considered in the reverse mro order to ensure base class markers are considered first +this resolves a regression. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 8dbff1dc93a..55620f0429e 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -373,7 +373,9 @@ def get_unpacked_marks( if not consider_mro: mark_lists = [obj.__dict__.get("pytestmark", [])] else: - mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__] + mark_lists = [ + x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__) + ] mark_list = [] for item in mark_lists: if isinstance(item, list): diff --git a/testing/test_mark.py b/testing/test_mark.py index e2d1a40c38a..2767260df8c 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1130,6 +1130,41 @@ class C(A, B): all_marks = get_unpacked_marks(C) - assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark] + assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark] assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark] + + +# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447") +def test_mark_fixture_order_mro(pytester: Pytester): + """This ensures we walk marks of the mro starting with the base classes + the action at a distance fixtures are taken as minimal example from a real project + + """ + foo = pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def add_attr1(request): + request.instance.attr1 = object() + + + @pytest.fixture + def add_attr2(request): + request.instance.attr2 = request.instance.attr1 + + + @pytest.mark.usefixtures('add_attr1') + class Parent: + pass + + + @pytest.mark.usefixtures('add_attr2') + class TestThings(Parent): + def test_attrs(self): + assert self.attr1 == self.attr2 + """ + ) + result = pytester.runpytest(foo) + result.assert_outcomes(passed=1) From a0714aa0076f38e6fb8c7321e8bb4f5f33d1792d Mon Sep 17 00:00:00 2001 From: pytest bot Date: Tue, 24 Oct 2023 18:43:16 +0000 Subject: [PATCH 156/157] Prepare release version 7.4.3 --- changelog/10447.bugfix.rst | 2 -- changelog/11239.bugfix.rst | 1 - changelog/11439.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.3.rst | 19 +++++++++++++++++++ doc/en/changelog.rst | 16 ++++++++++++++++ doc/en/getting-started.rst | 2 +- 7 files changed, 37 insertions(+), 5 deletions(-) delete mode 100644 changelog/10447.bugfix.rst delete mode 100644 changelog/11239.bugfix.rst delete mode 100644 changelog/11439.bugfix.rst create mode 100644 doc/en/announce/release-7.4.3.rst diff --git a/changelog/10447.bugfix.rst b/changelog/10447.bugfix.rst deleted file mode 100644 index fff94b28fb5..00000000000 --- a/changelog/10447.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -markers are now considered in the reverse mro order to ensure base class markers are considered first -this resolves a regression. diff --git a/changelog/11239.bugfix.rst b/changelog/11239.bugfix.rst deleted file mode 100644 index a486224cdda..00000000000 --- a/changelog/11239.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``:=`` in asserts impacting unrelated test cases. diff --git a/changelog/11439.bugfix.rst b/changelog/11439.bugfix.rst deleted file mode 100644 index b5104b1bcab..00000000000 --- a/changelog/11439.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 39fdfc13776..854666f6725 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.3 release-7.4.2 release-7.4.1 release-7.4.0 diff --git a/doc/en/announce/release-7.4.3.rst b/doc/en/announce/release-7.4.3.rst new file mode 100644 index 00000000000..0f319c1e7f0 --- /dev/null +++ b/doc/en/announce/release-7.4.3.rst @@ -0,0 +1,19 @@ +pytest-7.4.3 +======================================= + +pytest 7.4.3 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +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 +* Marc Mueller + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index ecfeeb662b6..f9c6130c24f 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,22 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.3 (2023-10-24) +========================= + +Bug Fixes +--------- + +- `#10447 `_: markers are now considered in the reverse mro order to ensure base class markers are considered first + this resolves a regression. + + +- `#11239 `_: Fixed ``:=`` in asserts impacting unrelated test cases. + + +- `#11439 `_: Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. + + pytest 7.4.2 (2023-09-07) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index e426e0c5072..ba6facd4cd9 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 7.4.2 + pytest 7.4.3 .. _`simpletest`: From 23906106968eb95afbd61adfbc7bbb795fc9aaa9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 24 Oct 2023 15:45:08 -0300 Subject: [PATCH 157/157] Tweak changelog.rst --- doc/en/changelog.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index f9c6130c24f..121d1708da7 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -34,14 +34,13 @@ pytest 7.4.3 (2023-10-24) Bug Fixes --------- -- `#10447 `_: markers are now considered in the reverse mro order to ensure base class markers are considered first - this resolves a regression. +- `#10447 `_: Markers are now considered in the reverse mro order to ensure base class markers are considered first -- this resolves a regression. - `#11239 `_: Fixed ``:=`` in asserts impacting unrelated test cases. -- `#11439 `_: Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. +- `#11439 `_: Handled an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. pytest 7.4.2 (2023-09-07)