Merge branch 'pytest-dev:main' into issue-11037

This commit is contained in:
OlegP-andrew 2023-12-06 19:12:08 -05:00 committed by GitHub
commit ebe2257919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 944 additions and 578 deletions

View File

@ -47,7 +47,7 @@ jobs:
path: dist path: dist
- name: Publish package to PyPI - name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@v1.8.10 uses: pypa/gh-action-pypi-publish@v1.8.11
- name: Push tag - name: Push tag
run: | run: |

View File

@ -56,7 +56,7 @@ repos:
hooks: hooks:
- id: python-use-type-annotations - id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.0 rev: v1.7.1
hooks: hooks:
- id: mypy - id: mypy
files: ^(src/|testing/) files: ^(src/|testing/)

View File

@ -188,6 +188,7 @@ Javier Romero
Jeff Rackauckas Jeff Rackauckas
Jeff Widman Jeff Widman
Jenni Rinker Jenni Rinker
Jens Tröger
John Eddie Ayson John Eddie Ayson
John Litborn John Litborn
John Towler John Towler

View File

@ -1 +1,3 @@
Improved very verbose diff output to color it as a diff instead of only red. Improved very verbose diff output to color it as a diff instead of only red.
Improved the error reporting to better separate each section.

View File

@ -0,0 +1 @@
Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down.

View File

@ -0,0 +1,2 @@
Added :func:`LogCaptureFixture.filtering() <pytest.LogCaptureFixture.filtering>` context manager that
adds a given :class:`logging.Filter` object to the caplog fixture.

View File

@ -0,0 +1 @@
Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment.

View File

@ -0,0 +1,3 @@
pytest's ``setup.py`` file is removed.
If you relied on this file, e.g. to install pytest using ``setup.py install``,
please see `Why you shouldn't invoke setup.py directly <https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html#summary>`_ for alternatives.

View File

@ -0,0 +1,4 @@
Improved the very verbose diff for every standard library container types: the indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users.
Previously, the default python pretty printer was used to generate the output, which puts opening and closing
markers on the same line as the first/last entry, in addition to not having consistent indentation.

View File

@ -241,7 +241,7 @@ through ``add_color_level()``. Example:
.. code-block:: python .. code-block:: python
@pytest.hookimpl @pytest.hookimpl(trylast=True)
def pytest_configure(config): def pytest_configure(config):
logging_plugin = config.pluginmanager.get_plugin("logging-plugin") logging_plugin = config.pluginmanager.get_plugin("logging-plugin")

View File

@ -27,7 +27,7 @@ please refer to `the update script <https://github.com/pytest-dev/pytest/blob/ma
creating a PDF, because otherwise the table gets far too wide for the creating a PDF, because otherwise the table gets far too wide for the
page. page.
This list contains 1346 plugins. This list contains 1351 plugins.
.. only:: not latex .. only:: not latex
@ -78,7 +78,7 @@ This list contains 1346 plugins.
:pypi:`pytest-antilru` Bust functools.lru_cache when running pytest to avoid test pollution Jul 05, 2022 5 - Production/Stable pytest :pypi:`pytest-antilru` Bust functools.lru_cache when running pytest to avoid test pollution Jul 05, 2022 5 - Production/Stable pytest
:pypi:`pytest-anyio` The pytest anyio plugin is built into anyio. You don't need this package. Jun 29, 2021 N/A pytest :pypi:`pytest-anyio` The pytest anyio plugin is built into anyio. You don't need this package. Jun 29, 2021 N/A pytest
:pypi:`pytest-anything` Pytest fixtures to assert anything and something Oct 13, 2022 N/A pytest :pypi:`pytest-anything` Pytest fixtures to assert anything and something Oct 13, 2022 N/A pytest
:pypi:`pytest-aoc` Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures Sep 19, 2023 5 - Production/Stable pytest ; extra == 'test' :pypi:`pytest-aoc` Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures Dec 02, 2023 5 - Production/Stable pytest ; extra == 'test'
:pypi:`pytest-aoreporter` pytest report Jun 27, 2022 N/A N/A :pypi:`pytest-aoreporter` pytest report Jun 27, 2022 N/A N/A
:pypi:`pytest-api` An ASGI middleware to populate OpenAPI Specification examples from pytest functions May 12, 2022 N/A pytest (>=7.1.1,<8.0.0) :pypi:`pytest-api` An ASGI middleware to populate OpenAPI Specification examples from pytest functions May 12, 2022 N/A pytest (>=7.1.1,<8.0.0)
:pypi:`pytest-api-soup` Validate multiple endpoints with unit testing using a single source of truth. Aug 27, 2022 N/A N/A :pypi:`pytest-api-soup` Validate multiple endpoints with unit testing using a single source of truth. Aug 27, 2022 N/A N/A
@ -89,7 +89,7 @@ This list contains 1346 plugins.
:pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Sep 06, 2023 5 - Production/Stable pytest :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Sep 06, 2023 5 - Production/Stable pytest
:pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2) :pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2)
:pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4) :pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4)
:pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Nov 15, 2023 4 - Beta pytest >=4.6 :pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Nov 27, 2023 4 - Beta pytest >=4.6
:pypi:`pytest-asgi-server` Convenient ASGI client/server fixtures for Pytest Dec 12, 2020 N/A pytest (>=5.4.1) :pypi:`pytest-asgi-server` Convenient ASGI client/server fixtures for Pytest Dec 12, 2020 N/A pytest (>=5.4.1)
:pypi:`pytest-aspec` A rspec format reporter for pytest Oct 23, 2023 4 - Beta N/A :pypi:`pytest-aspec` A rspec format reporter for pytest Oct 23, 2023 4 - Beta N/A
:pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A :pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A
@ -105,12 +105,12 @@ This list contains 1346 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-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-ast-transformer` May 04, 2019 3 - Alpha pytest
:pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A
:pypi:`pytest-asyncio` Pytest support for asyncio Nov 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-asyncio` Pytest support for asyncio Nov 27, 2023 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Aug 06, 2023 N/A N/A :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Nov 30, 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-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-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) :pypi:`pytest-async-sqlalchemy` Database testing fixtures using the SQLAlchemy asyncio API Oct 07, 2021 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-atf-allure` 基于allure-pytest进行自定义 Oct 22, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-atf-allure` 基于allure-pytest进行自定义 Nov 29, 2023 N/A pytest (>=7.4.2,<8.0.0)
:pypi:`pytest-atomic` Skip rest of tests if previous test failed. Nov 24, 2018 4 - Beta N/A :pypi:`pytest-atomic` Skip rest of tests if previous test failed. Nov 24, 2018 4 - Beta N/A
:pypi:`pytest-attrib` pytest plugin to select tests based on attributes similar to the nose-attrib plugin May 24, 2016 4 - Beta N/A :pypi:`pytest-attrib` pytest plugin to select tests based on attributes similar to the nose-attrib plugin May 24, 2016 4 - Beta N/A
:pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A
@ -207,7 +207,7 @@ This list contains 1346 plugins.
:pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest
:pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A
:pypi:`pytest-chic-report` A pytest plugin to send a report and printing summary of tests. Jan 31, 2023 5 - Production/Stable N/A :pypi:`pytest-chic-report` A pytest plugin to send a report and printing summary of tests. Jan 31, 2023 5 - Production/Stable N/A
:pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Nov 02, 2023 N/A pytest >=7.0.0 :pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Nov 30, 2023 N/A pytest >=7.0.0
:pypi:`pytest-chunks` Run only a chunk of your test suite Jul 05, 2022 N/A pytest (>=6.0.0) :pypi:`pytest-chunks` Run only a chunk of your test suite Jul 05, 2022 N/A pytest (>=6.0.0)
:pypi:`pytest-circleci` py.test plugin for CircleCI May 03, 2019 N/A N/A :pypi:`pytest-circleci` py.test plugin for CircleCI May 03, 2019 N/A N/A
:pypi:`pytest-circleci-parallelized` Parallelize pytest across CircleCI workers. Oct 20, 2022 N/A N/A :pypi:`pytest-circleci-parallelized` Parallelize pytest across CircleCI workers. Oct 20, 2022 N/A N/A
@ -379,7 +379,7 @@ This list contains 1346 plugins.
: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-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. Aug 11, 2023 3 - Alpha pytest >=4.6 :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Aug 11, 2023 3 - Alpha pytest >=4.6
:pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 2023 N/A N/A :pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 2023 N/A N/A
:pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Aug 04, 2023 N/A N/A :pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Nov 20, 2023 N/A N/A
:pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4)
:pypi:`pytest-donde` record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. Oct 01, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-donde` record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. Oct 01, 2023 4 - Beta pytest >=7.3.1
:pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0)
@ -410,14 +410,14 @@ This list contains 1346 plugins.
:pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :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-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-email` Send execution result email Jul 08, 2020 N/A pytest
:pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Nov 07, 2023 5 - Production/Stable pytest>=7.0 :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Nov 27, 2023 5 - Production/Stable pytest>=7.0
:pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 27, 2023 5 - Production/Stable N/A
:pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 07, 2023 5 - Production/Stable N/A :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 27, 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-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` 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-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1)
@ -427,7 +427,7 @@ This list contains 1346 plugins.
:pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest
:pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A :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-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A
:pypi:`pytest-env` pytest plugin that allows you to add environment variables. Oct 30, 2023 5 - Production/Stable pytest>=7.4.3 :pypi:`pytest-env` pytest plugin that allows you to add environment variables. Nov 28, 2023 5 - Production/Stable pytest>=7.4.3
:pypi:`pytest-envfiles` A py.test plugin that parses environment files before running tests Oct 08, 2015 3 - Alpha N/A :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-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) :pypi:`pytest-envraw` py.test plugin that allows you to add environment variables. Aug 27, 2020 4 - Beta pytest (>=2.6.0)
@ -527,15 +527,16 @@ This list contains 1346 plugins.
:pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0
:pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A
:pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A
:pypi:`pytest-fzf` fzf-based test selector for pytest Nov 15, 2023 1 - Planning pytest >=7.1.2 :pypi:`pytest-fzf` fzf-based test selector for pytest Nov 28, 2023 4 - Beta pytest >=6.0.0
:pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Apr 12, 2022 N/A pytest (>=6.0.0) :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Apr 12, 2022 N/A pytest (>=6.0.0)
:pypi:`pytest-gc` The garbage collector plugin for py.test Feb 01, 2018 N/A N/A :pypi:`pytest-gc` The garbage collector plugin for py.test Feb 01, 2018 N/A N/A
:pypi:`pytest-gcov` Uses gcov to measure test coverage of a C library Feb 01, 2018 3 - Alpha N/A :pypi:`pytest-gcov` Uses gcov to measure test coverage of a C library Feb 01, 2018 3 - Alpha N/A
:pypi:`pytest-gee` The Python plugin for your GEE based packages. Nov 22, 2023 3 - Alpha pytest; extra == 'test'
:pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest
:pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :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-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-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. Nov 08, 2023 N/A N/A :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 20, 2023 N/A N/A
:pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 15, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 15, 2023 4 - Beta pytest>=7.1.2
:pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A
@ -570,12 +571,13 @@ This list contains 1346 plugins.
:pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5)
:pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :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-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-history` Pytest plugin to keep a history of your pytest runs Nov 20, 2023 N/A pytest (>=7.4.3,<8.0.0)
:pypi:`pytest-home` Home directory fixtures Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest-home` Home directory fixtures Oct 09, 2023 5 - Production/Stable pytest
:pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A :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 Nov 11, 2023 3 - Alpha pytest ==7.4.3 :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 01, 2023 3 - Alpha pytest ==7.4.3
:pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :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-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A
:pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A :pypi:`pytest-hot-reloading` Dec 01, 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-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Nov 10, 2023 N/A pytest :pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Nov 10, 2023 N/A pytest
:pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0)
@ -611,7 +613,7 @@ This list contains 1346 plugins.
:pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Oct 11, 2023 5 - Production/Stable pytest >=6.0 :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Oct 11, 2023 5 - Production/Stable pytest >=6.0
:pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Aug 17, 2023 2 - Pre-Alpha pytest>=7.0 :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Aug 17, 2023 2 - Pre-Alpha pytest>=7.0
:pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest :pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest
:pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Nov 16, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Dec 01, 2023 4 - Beta pytest >=3.5.0
:pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A
:pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A
:pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A
@ -620,9 +622,9 @@ This list contains 1346 plugins.
:pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A
:pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :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. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0
:pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Nov 29, 2023 5 - Production/Stable N/A
:pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 13, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 13, 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-lsm` Common fixtures for inmanta LSM related modules Nov 29, 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-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-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) :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0)
@ -632,7 +634,7 @@ This list contains 1346 plugins.
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest May 22, 2023 N/A pytest (>=5.2) :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-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-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. Sep 14, 2023 4 - Beta pytest :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Nov 29, 2023 4 - Beta pytest
:pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 31, 2023 5 - Production/Stable pytest <7.2.0,>=6 :pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 31, 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-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-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A
@ -697,7 +699,7 @@ This list contains 1346 plugins.
:pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0)
:pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-litf` A pytest plugin that stream output in LITF format Jan 18, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-litf` A pytest plugin that stream output in LITF format Jan 18, 2021 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Aug 08, 2023 4 - Beta pytest >=6.1 :pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Nov 23, 2023 4 - Beta pytest >=6.1
:pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest :pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest
:pypi:`pytest-local-badge` Generate local badges (shields) reporting your test suite status. Jan 15, 2023 N/A pytest (>=6.1.0) :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 14, 2023 5 - Production/Stable pytest :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 14, 2023 5 - Production/Stable pytest
@ -747,7 +749,7 @@ This list contains 1346 plugins.
:pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :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-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-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest
:pypi:`pytest-mh` Pytest multihost plugin Sep 27, 2023 N/A pytest :pypi:`pytest-mh` Pytest multihost plugin Nov 21, 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-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-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-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0)
@ -838,7 +840,7 @@ This list contains 1346 plugins.
:pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A
:pypi:`pytest-optional-tests` Easy declaration of optional tests (i.e., that are not run by default) Jul 09, 2019 4 - Beta pytest (>=4.5.0) :pypi:`pytest-optional-tests` Easy declaration of optional tests (i.e., that are not run by default) Jul 09, 2019 4 - Beta pytest (>=4.5.0)
:pypi:`pytest-orchestration` A pytest plugin for orchestrating tests Jul 18, 2019 N/A N/A :pypi:`pytest-orchestration` A pytest plugin for orchestrating tests Jul 18, 2019 N/A N/A
:pypi:`pytest-order` pytest plugin to run your tests in a specific order Mar 10, 2023 4 - Beta pytest (>=5.0) ; python_version < "3.10" :pypi:`pytest-order` pytest plugin to run your tests in a specific order Nov 18, 2023 4 - Beta pytest >=5.0 ; python_version < "3.10"
:pypi:`pytest-ordering` pytest plugin to run your tests in a specific order Nov 14, 2018 4 - Beta pytest :pypi:`pytest-ordering` pytest plugin to run your tests in a specific order Nov 14, 2018 4 - Beta pytest
:pypi:`pytest-order-modify` 新增run_marker 来自定义用例的执行顺序 Nov 04, 2022 N/A N/A :pypi:`pytest-order-modify` 新增run_marker 来自定义用例的执行顺序 Nov 04, 2022 N/A N/A
:pypi:`pytest-osxnotify` OS X notifications for py.test results. May 15, 2015 N/A N/A :pypi:`pytest-osxnotify` OS X notifications for py.test results. May 15, 2015 N/A N/A
@ -863,6 +865,7 @@ This list contains 1346 plugins.
:pypi:`pytest-paste-config` Allow setting the path to a paste config file Sep 18, 2013 3 - Alpha N/A :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-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-patches` A contextmanager pytest fixture for handling multiple mock patches Aug 30, 2021 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-patterns` pytest plugin to make testing complicated long string output easy to write and easy to debug Nov 17, 2023 4 - Beta N/A
:pypi:`pytest-pdb` pytest plugin which adds pdb helper commands related to pytest. Jul 31, 2018 N/A N/A :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) :pypi:`pytest-peach` pytest plugin for fuzzing with Peach API Security Apr 12, 2019 4 - Beta pytest (>=2.8.7)
:pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A
@ -939,7 +942,7 @@ This list contains 1346 plugins.
:pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :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 Oct 06, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0
:pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A :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 Nov 04, 2023 N/A pytest :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 18, 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-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-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-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0)
@ -957,7 +960,7 @@ This list contains 1346 plugins.
:pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 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-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-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 30, 2023 5 - Production/Stable pytest (>=6.2.5) :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Nov 29, 2023 5 - Production/Stable pytest >=6.0
:pypi:`pytest-qml` Run QML Tests with pytest Dec 02, 2020 4 - Beta pytest (>=6.0.0) :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-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` pytest support for PyQt and PySide applications Oct 25, 2022 5 - Production/Stable pytest (>=3.0.0)
@ -978,8 +981,8 @@ This list contains 1346 plugins.
:pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A
:pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0)
:pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A
:pypi:`pytest-reana` Pytest fixtures for REANA. Sep 26, 2023 3 - Alpha N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Nov 30, 2023 3 - Alpha N/A
: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-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Nov 21, 2023 N/A N/A
:pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 31, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 31, 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-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. Apr 19, 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)
@ -1020,10 +1023,10 @@ This list contains 1346 plugins.
:pypi:`pytest-reraise` Make multi-threaded pytest test cases fail when they should Sep 20, 2022 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-reraise` Make multi-threaded pytest test cases fail when they should Sep 20, 2022 5 - Production/Stable pytest (>=4.6)
:pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6) :pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6)
:pypi:`pytest-rerun-all` Rerun testsuite for a certain time or iterations Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-rerun-all` Rerun testsuite for a certain time or iterations Nov 16, 2023 3 - Alpha pytest (>=7.0.0)
:pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Jul 05, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 22, 2023 5 - Production/Stable pytest >=7
: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-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. Aug 31, 2023 4 - Beta pytest :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Aug 31, 2023 4 - Beta pytest
:pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Oct 05, 2023 N/A pytest ~=4.6 ; python_version == "2.7" :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Nov 22, 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` 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-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 :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0
@ -1064,22 +1067,22 @@ This list contains 1346 plugins.
: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-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 :pypi:`pytest-salt` Pytest Salt Plugin Jan 27, 2020 4 - Beta N/A
:pypi:`pytest-salt-containers` A Pytest plugin that builds and creates docker containers Nov 09, 2016 4 - Beta N/A :pypi:`pytest-salt-containers` A Pytest plugin that builds and creates docker containers Nov 09, 2016 4 - Beta N/A
:pypi:`pytest-salt-factories` Pytest Salt Plugin Sep 27, 2023 4 - Beta pytest (>=6.0.0) :pypi:`pytest-salt-factories` Pytest Salt Plugin Nov 25, 2023 4 - Beta pytest (>=6.0.0)
:pypi:`pytest-salt-from-filenames` Simple PyTest Plugin For Salt's Test Suite Specifically Jan 29, 2019 4 - Beta pytest (>=4.1) :pypi:`pytest-salt-from-filenames` Simple PyTest Plugin For Salt's Test Suite Specifically Jan 29, 2019 4 - Beta pytest (>=4.1)
:pypi:`pytest-salt-runtests-bridge` Simple PyTest Plugin For Salt's Test Suite Specifically Dec 05, 2019 4 - Beta pytest (>=4.1) :pypi:`pytest-salt-runtests-bridge` Simple PyTest Plugin For Salt's Test Suite Specifically Dec 05, 2019 4 - Beta pytest (>=4.1)
:pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :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-sanity` Dec 07, 2020 N/A N/A
:pypi:`pytest-sa-pg` May 14, 2019 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. Nov 17, 2023 5 - Production/Stable N/A :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 01, 2023 5 - Production/Stable N/A
:pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha 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-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-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0)
:pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 21, 2023 4 - Beta N/A :pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 21, 2023 4 - Beta N/A
:pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :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-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-selenium` pytest plugin for Selenium Nov 20, 2023 5 - Production/Stable pytest>=6.0.0
:pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Nov 07, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Nov 07, 2023 N/A pytest >= 7.0.0
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 17, 2023 5 - Production/Stable N/A :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 01, 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-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-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-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A
@ -1111,6 +1114,7 @@ This list contains 1346 plugins.
:pypi:`pytest-skipper` A plugin that selects only tests with changes in execution path Mar 26, 2017 3 - Alpha pytest (>=3.0.6) :pypi:`pytest-skipper` A plugin that selects only tests with changes in execution path Mar 26, 2017 3 - Alpha pytest (>=3.0.6)
:pypi:`pytest-skippy` Automatically skip tests that don't need to run! Jan 27, 2018 3 - Alpha pytest (>=2.3.4) :pypi:`pytest-skippy` Automatically skip tests that don't need to run! Jan 27, 2018 3 - Alpha pytest (>=2.3.4)
:pypi:`pytest-skip-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Feb 09, 2023 N/A pytest>=6.2.0 :pypi:`pytest-skip-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Feb 09, 2023 N/A pytest>=6.2.0
:pypi:`pytest-skipuntil` A simple pytest plugin to skip flapping test with deadline Nov 25, 2023 4 - Beta pytest >=3.8.0
:pypi:`pytest-slack` Pytest to Slack reporting plugin Dec 15, 2020 5 - Production/Stable N/A :pypi:`pytest-slack` Pytest to Slack reporting plugin Dec 15, 2020 5 - Production/Stable N/A
:pypi:`pytest-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Sep 28, 2021 N/A N/A :pypi:`pytest-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Sep 28, 2021 N/A N/A
:pypi:`pytest-slowest-first` Sort tests by their last duration, slowest first Dec 11, 2022 4 - Beta N/A :pypi:`pytest-slowest-first` Sort tests by their last duration, slowest first Dec 11, 2022 4 - Beta N/A
@ -1139,7 +1143,7 @@ This list contains 1346 plugins.
:pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest
:pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A
:pypi:`pytest-spec` Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. May 04, 2021 N/A N/A :pypi:`pytest-spec` Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. May 04, 2021 N/A N/A
:pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Sep 15, 2023 N/A pytest (>7.0) :pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Nov 21, 2023 N/A pytest (>7.0)
:pypi:`pytest-speed` Modern benchmarking library for python with pytest integration. Jan 22, 2023 3 - Alpha pytest>=7 :pypi:`pytest-speed` Modern benchmarking library for python with pytest integration. Jan 22, 2023 3 - Alpha pytest>=7
:pypi:`pytest-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Sep 06, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Sep 06, 2022 4 - Beta pytest (>=7.0.0)
:pypi:`pytest-spiratest` Exports unit tests as test runs in SpiraTest/Team/Plan Feb 08, 2022 N/A N/A :pypi:`pytest-spiratest` Exports unit tests as test runs in SpiraTest/Team/Plan Feb 08, 2022 N/A N/A
@ -1150,8 +1154,8 @@ This list contains 1346 plugins.
:pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :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` 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 :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A
:pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Oct 23, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Nov 25, 2023 N/A pytest (>5.4.0,<8)
:pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 2023 N/A N/A :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Dec 01, 2023 N/A N/A
:pypi:`pytest-splunk-env` pytest fixtures for interaction with Splunk Enterprise and Splunk Cloud Oct 22, 2020 N/A pytest (>=6.1.1,<7.0.0) :pypi:`pytest-splunk-env` pytest fixtures for interaction with Splunk Enterprise and Splunk Cloud Oct 22, 2020 N/A pytest (>=6.1.1,<7.0.0)
:pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A :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` pytest plugin with sqlalchemy related fixtures Mar 13, 2018 3 - Alpha N/A
@ -1178,6 +1182,7 @@ This list contains 1346 plugins.
:pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A
:pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0)
: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-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-subinterpreter` Run pytest in a subinterpreter Nov 25, 2023 N/A pytest>=7.0.0
:pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jan 28, 2023 5 - Production/Stable pytest (>=4.0.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-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 May 15, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-subtests` unittest subTest() support and subtests fixture May 15, 2023 4 - Beta pytest (>=7.0)
@ -1217,7 +1222,7 @@ This list contains 1346 plugins.
:pypi:`pytest-testinfra-jpic` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A :pypi:`pytest-testinfra-jpic` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A
:pypi:`pytest-testinfra-winrm-transport` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A :pypi:`pytest-testinfra-winrm-transport` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A
:pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) :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 Nov 07, 2023 4 - Beta pytest <8,>=5 :pypi:`pytest-testmon` selects tests affected by changed files and methods Nov 23, 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-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-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) :pypi:`pytest-testmon-skip-libraries` selects tests affected by changed files and methods Mar 03, 2023 4 - Beta pytest (<8,>=5)
@ -1290,7 +1295,7 @@ This list contains 1346 plugins.
:pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) :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-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-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A
:pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Nov 17, 2023 4 - Beta N/A :pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Dec 01, 2023 4 - Beta N/A
:pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A
:pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :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-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A
@ -1315,8 +1320,8 @@ This list contains 1346 plugins.
: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) :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)
:pypi:`pytest-vcrpandas` Test from HTTP interactions to dataframe processed. Jan 12, 2019 4 - Beta pytest :pypi:`pytest-vcrpandas` Test from HTTP interactions to dataframe processed. Jan 12, 2019 4 - Beta pytest
:pypi:`pytest-vcs` Sep 22, 2022 4 - Beta N/A :pypi:`pytest-vcs` Sep 22, 2022 4 - Beta N/A
:pypi:`pytest-venv` py.test fixture for creating a virtual environment Aug 04, 2020 4 - Beta pytest :pypi:`pytest-venv` py.test fixture for creating a virtual environment Nov 23, 2023 4 - Beta pytest
:pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 18, 2023 4 - Beta pytest :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 23, 2023 4 - Beta pytest
:pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-vimqf` A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. Feb 08, 2021 4 - Beta pytest (>=6.2.2,<7.0.0) :pypi:`pytest-vimqf` A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. Feb 08, 2021 4 - Beta pytest (>=6.2.2,<7.0.0)
:pypi:`pytest-virtualenv` Virtualenv fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-virtualenv` Virtualenv fixture for py.test May 28, 2019 5 - Production/Stable pytest
@ -1346,7 +1351,7 @@ This list contains 1346 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-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-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-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 Nov 11, 2023 5 - Production/Stable pytest >=6.2.0 :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Nov 21, 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-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-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-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1)
@ -1365,7 +1370,7 @@ This list contains 1346 plugins.
: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-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1)
:pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2023 4 - Beta pytest >=7.1.0 :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2023 4 - Beta pytest >=7.1.0
: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` 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 Jul 03, 2023 N/A pytest>=7.4.0 :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Nov 30, 2023 N/A pytest>=7.4.0
:pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :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-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 Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 19, 2023 N/A pytest (>=7.2.0)
@ -1694,7 +1699,7 @@ This list contains 1346 plugins.
Pytest fixtures to assert anything and something Pytest fixtures to assert anything and something
:pypi:`pytest-aoc` :pypi:`pytest-aoc`
*last release*: Sep 19, 2023, *last release*: Dec 02, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest ; extra == 'test' *requires*: pytest ; extra == 'test'
@ -1771,7 +1776,7 @@ This list contains 1346 plugins.
pyest results colection plugin pyest results colection plugin
:pypi:`pytest-arraydiff` :pypi:`pytest-arraydiff`
*last release*: Nov 15, 2023, *last release*: Nov 27, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest >=4.6 *requires*: pytest >=4.6
@ -1883,14 +1888,14 @@ This list contains 1346 plugins.
Pytest fixtures for async generators Pytest fixtures for async generators
:pypi:`pytest-asyncio` :pypi:`pytest-asyncio`
*last release*: Nov 16, 2023, *last release*: Nov 27, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=7.0.0) *requires*: pytest (>=7.0.0)
Pytest support for asyncio Pytest support for asyncio
:pypi:`pytest-asyncio-cooperative` :pypi:`pytest-asyncio-cooperative`
*last release*: Aug 06, 2023, *last release*: Nov 30, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -1918,7 +1923,7 @@ This list contains 1346 plugins.
Database testing fixtures using the SQLAlchemy asyncio API Database testing fixtures using the SQLAlchemy asyncio API
:pypi:`pytest-atf-allure` :pypi:`pytest-atf-allure`
*last release*: Oct 22, 2023, *last release*: Nov 29, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest (>=7.4.2,<8.0.0) *requires*: pytest (>=7.4.2,<8.0.0)
@ -2597,7 +2602,7 @@ This list contains 1346 plugins.
A pytest plugin to send a report and printing summary of tests. A pytest plugin to send a report and printing summary of tests.
:pypi:`pytest-choose` :pypi:`pytest-choose`
*last release*: Nov 02, 2023, *last release*: Nov 30, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest >=7.0.0 *requires*: pytest >=7.0.0
@ -3801,7 +3806,7 @@ This list contains 1346 plugins.
pytest plugin for dogu report pytest plugin for dogu report
:pypi:`pytest-dogu-sdk` :pypi:`pytest-dogu-sdk`
*last release*: Aug 04, 2023, *last release*: Nov 20, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -4018,56 +4023,56 @@ This list contains 1346 plugins.
Send execution result email Send execution result email
:pypi:`pytest-embedded` :pypi:`pytest-embedded`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest>=7.0 *requires*: pytest>=7.0
A pytest plugin that designed for embedded testing. A pytest plugin that designed for embedded testing.
:pypi:`pytest-embedded-arduino` :pypi:`pytest-embedded-arduino`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with Arduino. Make pytest-embedded plugin work with Arduino.
:pypi:`pytest-embedded-idf` :pypi:`pytest-embedded-idf`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with ESP-IDF. Make pytest-embedded plugin work with ESP-IDF.
:pypi:`pytest-embedded-jtag` :pypi:`pytest-embedded-jtag`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with JTAG. Make pytest-embedded plugin work with JTAG.
:pypi:`pytest-embedded-qemu` :pypi:`pytest-embedded-qemu`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with QEMU. Make pytest-embedded plugin work with QEMU.
:pypi:`pytest-embedded-serial` :pypi:`pytest-embedded-serial`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with Serial. Make pytest-embedded plugin work with Serial.
:pypi:`pytest-embedded-serial-esp` :pypi:`pytest-embedded-serial-esp`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
Make pytest-embedded plugin work with Espressif target boards. Make pytest-embedded plugin work with Espressif target boards.
:pypi:`pytest-embedded-wokwi` :pypi:`pytest-embedded-wokwi`
*last release*: Nov 07, 2023, *last release*: Nov 27, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -4137,7 +4142,7 @@ This list contains 1346 plugins.
Improvements for pytest (rejected upstream) Improvements for pytest (rejected upstream)
:pypi:`pytest-env` :pypi:`pytest-env`
*last release*: Oct 30, 2023, *last release*: Nov 28, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest>=7.4.3 *requires*: pytest>=7.4.3
@ -4837,9 +4842,9 @@ This list contains 1346 plugins.
:pypi:`pytest-fzf` :pypi:`pytest-fzf`
*last release*: Nov 15, 2023, *last release*: Nov 28, 2023,
*status*: 1 - Planning, *status*: 4 - Beta,
*requires*: pytest >=7.1.2 *requires*: pytest >=6.0.0
fzf-based test selector for pytest fzf-based test selector for pytest
@ -4864,6 +4869,13 @@ This list contains 1346 plugins.
Uses gcov to measure test coverage of a C library Uses gcov to measure test coverage of a C library
:pypi:`pytest-gee`
*last release*: Nov 22, 2023,
*status*: 3 - Alpha,
*requires*: pytest; extra == 'test'
The Python plugin for your GEE based packages.
:pypi:`pytest-gevent` :pypi:`pytest-gevent`
*last release*: Feb 25, 2020, *last release*: Feb 25, 2020,
*status*: N/A, *status*: N/A,
@ -4893,7 +4905,7 @@ This list contains 1346 plugins.
For finding/executing Ghost Inspector tests For finding/executing Ghost Inspector tests
:pypi:`pytest-girder` :pypi:`pytest-girder`
*last release*: Nov 08, 2023, *last release*: Nov 20, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -5137,6 +5149,13 @@ This list contains 1346 plugins.
Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report
:pypi:`pytest-history`
*last release*: Nov 20, 2023,
*status*: N/A,
*requires*: pytest (>=7.4.3,<8.0.0)
Pytest plugin to keep a history of your pytest runs
:pypi:`pytest-home` :pypi:`pytest-home`
*last release*: Oct 09, 2023, *last release*: Oct 09, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
@ -5152,7 +5171,7 @@ This list contains 1346 plugins.
A pytest plugin for use with homeassistant custom components. A pytest plugin for use with homeassistant custom components.
:pypi:`pytest-homeassistant-custom-component` :pypi:`pytest-homeassistant-custom-component`
*last release*: Nov 11, 2023, *last release*: Dec 01, 2023,
*status*: 3 - Alpha, *status*: 3 - Alpha,
*requires*: pytest ==7.4.3 *requires*: pytest ==7.4.3
@ -5173,7 +5192,7 @@ This list contains 1346 plugins.
Report on tests that honor constraints, and guard against regressions Report on tests that honor constraints, and guard against regressions
:pypi:`pytest-hot-reloading` :pypi:`pytest-hot-reloading`
*last release*: Jun 23, 2023, *last release*: Dec 01, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -5425,7 +5444,7 @@ This list contains 1346 plugins.
:pypi:`pytest-image-snapshot` :pypi:`pytest-image-snapshot`
*last release*: Nov 16, 2023, *last release*: Dec 01, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest >=3.5.0 *requires*: pytest >=3.5.0
@ -5488,7 +5507,7 @@ This list contains 1346 plugins.
A pytest plugin for writing inline tests. A pytest plugin for writing inline tests.
:pypi:`pytest-inmanta` :pypi:`pytest-inmanta`
*last release*: Aug 03, 2023, *last release*: Nov 29, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -5502,7 +5521,7 @@ This list contains 1346 plugins.
Inmanta tests package Inmanta tests package
:pypi:`pytest-inmanta-lsm` :pypi:`pytest-inmanta-lsm`
*last release*: May 17, 2023, *last release*: Nov 29, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -5572,7 +5591,7 @@ This list contains 1346 plugins.
Pytest plugin for intercepting outgoing connection requests during pytest run. Pytest plugin for intercepting outgoing connection requests during pytest run.
:pypi:`pytest-interface-tester` :pypi:`pytest-interface-tester`
*last release*: Sep 14, 2023, *last release*: Nov 29, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest *requires*: pytest
@ -6027,7 +6046,7 @@ This list contains 1346 plugins.
A pytest plugin that stream output in LITF format A pytest plugin that stream output in LITF format
:pypi:`pytest-litter` :pypi:`pytest-litter`
*last release*: Aug 08, 2023, *last release*: Nov 23, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest >=6.1 *requires*: pytest >=6.1
@ -6377,7 +6396,7 @@ This list contains 1346 plugins.
Custom metrics report for pytest Custom metrics report for pytest
:pypi:`pytest-mh` :pypi:`pytest-mh`
*last release*: Sep 27, 2023, *last release*: Nov 21, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest *requires*: pytest
@ -7014,9 +7033,9 @@ This list contains 1346 plugins.
A pytest plugin for orchestrating tests A pytest plugin for orchestrating tests
:pypi:`pytest-order` :pypi:`pytest-order`
*last release*: Mar 10, 2023, *last release*: Nov 18, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=5.0) ; python_version < "3.10" *requires*: pytest >=5.0 ; python_version < "3.10"
pytest plugin to run your tests in a specific order pytest plugin to run your tests in a specific order
@ -7188,6 +7207,13 @@ This list contains 1346 plugins.
A contextmanager pytest fixture for handling multiple mock patches A contextmanager pytest fixture for handling multiple mock patches
:pypi:`pytest-patterns`
*last release*: Nov 17, 2023,
*status*: 4 - Beta,
*requires*: N/A
pytest plugin to make testing complicated long string output easy to write and easy to debug
:pypi:`pytest-pdb` :pypi:`pytest-pdb`
*last release*: Jul 31, 2018, *last release*: Jul 31, 2018,
*status*: N/A, *status*: N/A,
@ -7721,7 +7747,7 @@ This list contains 1346 plugins.
Record PyMySQL queries and mock with the stored data. Record PyMySQL queries and mock with the stored data.
:pypi:`pytest-pyodide` :pypi:`pytest-pyodide`
*last release*: Nov 04, 2023, *last release*: Nov 18, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest *requires*: pytest
@ -7847,9 +7873,9 @@ This list contains 1346 plugins.
Pytest plugin for uploading test results to your QA Touch Testrun. Pytest plugin for uploading test results to your QA Touch Testrun.
:pypi:`pytest-qgis` :pypi:`pytest-qgis`
*last release*: Jun 30, 2023, *last release*: Nov 29, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest (>=6.2.5) *requires*: pytest >=6.0
A pytest plugin for testing QGIS python plugins A pytest plugin for testing QGIS python plugins
@ -7994,14 +8020,14 @@ This list contains 1346 plugins.
Test your README.md file Test your README.md file
:pypi:`pytest-reana` :pypi:`pytest-reana`
*last release*: Sep 26, 2023, *last release*: Nov 30, 2023,
*status*: 3 - Alpha, *status*: 3 - Alpha,
*requires*: N/A *requires*: N/A
Pytest fixtures for REANA. Pytest fixtures for REANA.
:pypi:`pytest-recorder` :pypi:`pytest-recorder`
*last release*: Mar 30, 2023, *last release*: Nov 21, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -8288,9 +8314,9 @@ This list contains 1346 plugins.
Rerun testsuite for a certain time or iterations Rerun testsuite for a certain time or iterations
:pypi:`pytest-rerunfailures` :pypi:`pytest-rerunfailures`
*last release*: Jul 05, 2023, *last release*: Nov 22, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest (>=6.2) *requires*: pytest >=7
pytest plugin to re-run tests to eliminate flaky failures pytest plugin to re-run tests to eliminate flaky failures
@ -8309,7 +8335,7 @@ This list contains 1346 plugins.
Pytest fixture for recording and replaying serial port traffic. Pytest fixture for recording and replaying serial port traffic.
:pypi:`pytest-resilient-circuits` :pypi:`pytest-resilient-circuits`
*last release*: Oct 05, 2023, *last release*: Nov 22, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest ~=4.6 ; python_version == "2.7" *requires*: pytest ~=4.6 ; python_version == "2.7"
@ -8596,7 +8622,7 @@ This list contains 1346 plugins.
A Pytest plugin that builds and creates docker containers A Pytest plugin that builds and creates docker containers
:pypi:`pytest-salt-factories` :pypi:`pytest-salt-factories`
*last release*: Sep 27, 2023, *last release*: Nov 25, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest (>=6.0.0) *requires*: pytest (>=6.0.0)
@ -8638,7 +8664,7 @@ This list contains 1346 plugins.
:pypi:`pytest-sbase` :pypi:`pytest-sbase`
*last release*: Nov 17, 2023, *last release*: Dec 01, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -8687,7 +8713,7 @@ This list contains 1346 plugins.
A pytest plugin which allows to (de-)select tests from a file. A pytest plugin which allows to (de-)select tests from a file.
:pypi:`pytest-selenium` :pypi:`pytest-selenium`
*last release*: May 28, 2023, *last release*: Nov 20, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest>=6.0.0 *requires*: pytest>=6.0.0
@ -8701,7 +8727,7 @@ This list contains 1346 plugins.
pytest plugin to automatically capture screenshots upon selenium webdriver events pytest plugin to automatically capture screenshots upon selenium webdriver events
:pypi:`pytest-seleniumbase` :pypi:`pytest-seleniumbase`
*last release*: Nov 17, 2023, *last release*: Dec 01, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: N/A *requires*: N/A
@ -8924,6 +8950,13 @@ This list contains 1346 plugins.
A pytest plugin to skip \`@pytest.mark.slow\` tests by default. A pytest plugin to skip \`@pytest.mark.slow\` tests by default.
:pypi:`pytest-skipuntil`
*last release*: Nov 25, 2023,
*status*: 4 - Beta,
*requires*: pytest >=3.8.0
A simple pytest plugin to skip flapping test with deadline
:pypi:`pytest-slack` :pypi:`pytest-slack`
*last release*: Dec 15, 2020, *last release*: Dec 15, 2020,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
@ -9121,7 +9154,7 @@ This list contains 1346 plugins.
Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION.
:pypi:`pytest-spec2md` :pypi:`pytest-spec2md`
*last release*: Sep 15, 2023, *last release*: Nov 21, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest (>7.0) *requires*: pytest (>7.0)
@ -9198,14 +9231,14 @@ This list contains 1346 plugins.
:pypi:`pytest-splunk-addon` :pypi:`pytest-splunk-addon`
*last release*: Oct 23, 2023, *last release*: Nov 25, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest (>5.4.0,<8) *requires*: pytest (>5.4.0,<8)
A Dynamic test tool for Splunk Apps and Add-ons A Dynamic test tool for Splunk Apps and Add-ons
:pypi:`pytest-splunk-addon-ui-smartx` :pypi:`pytest-splunk-addon-ui-smartx`
*last release*: Nov 15, 2023, *last release*: Dec 01, 2023,
*status*: N/A, *status*: N/A,
*requires*: N/A *requires*: N/A
@ -9393,6 +9426,13 @@ This list contains 1346 plugins.
A pytest plugin to organize long run tests (named studies) without interfering the regular tests A pytest plugin to organize long run tests (named studies) without interfering the regular tests
:pypi:`pytest-subinterpreter`
*last release*: Nov 25, 2023,
*status*: N/A,
*requires*: pytest>=7.0.0
Run pytest in a subinterpreter
:pypi:`pytest-subprocess` :pypi:`pytest-subprocess`
*last release*: Jan 28, 2023, *last release*: Jan 28, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
@ -9667,7 +9707,7 @@ This list contains 1346 plugins.
pytest reporting plugin for testlink pytest reporting plugin for testlink
:pypi:`pytest-testmon` :pypi:`pytest-testmon`
*last release*: Nov 07, 2023, *last release*: Nov 23, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest <8,>=5 *requires*: pytest <8,>=5
@ -10178,7 +10218,7 @@ This list contains 1346 plugins.
A Typhoon HIL plugin that facilitates test parameter configuration at runtime A Typhoon HIL plugin that facilitates test parameter configuration at runtime
:pypi:`pytest-typhoon-polarion` :pypi:`pytest-typhoon-polarion`
*last release*: Nov 17, 2023, *last release*: Dec 01, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: N/A *requires*: N/A
@ -10353,14 +10393,14 @@ This list contains 1346 plugins.
:pypi:`pytest-venv` :pypi:`pytest-venv`
*last release*: Aug 04, 2020, *last release*: Nov 23, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest *requires*: pytest
py.test fixture for creating a virtual environment py.test fixture for creating a virtual environment
:pypi:`pytest-ver` :pypi:`pytest-ver`
*last release*: Nov 18, 2023, *last release*: Nov 23, 2023,
*status*: 4 - Beta, *status*: 4 - Beta,
*requires*: pytest *requires*: pytest
@ -10570,7 +10610,7 @@ This list contains 1346 plugins.
A pytest plugin for configuring workflow/pipeline tests using YAML files A pytest plugin for configuring workflow/pipeline tests using YAML files
:pypi:`pytest-xdist` :pypi:`pytest-xdist`
*last release*: Nov 11, 2023, *last release*: Nov 21, 2023,
*status*: 5 - Production/Stable, *status*: 5 - Production/Stable,
*requires*: pytest >=6.2.0 *requires*: pytest >=6.2.0
@ -10703,7 +10743,7 @@ This list contains 1346 plugins.
This plugin is used to load yaml output to your test using pytest framework. This plugin is used to load yaml output to your test using pytest framework.
:pypi:`pytest-yaml-sanmu` :pypi:`pytest-yaml-sanmu`
*last release*: Jul 03, 2023, *last release*: Nov 30, 2023,
*status*: N/A, *status*: N/A,
*requires*: pytest>=7.4.0 *requires*: pytest>=7.4.0

View File

@ -1,6 +1,5 @@
[build-system] [build-system]
requires = [ requires = [
# sync with setup.py until we discard non-pep-517/518
"setuptools>=45.0", "setuptools>=45.0",
"setuptools-scm[toml]>=6.2.3", "setuptools-scm[toml]>=6.2.3",
] ]

View File

@ -1,4 +0,0 @@
from setuptools import setup
if __name__ == "__main__":
setup()

View File

@ -15,14 +15,17 @@
import collections as _collections import collections as _collections
import dataclasses as _dataclasses import dataclasses as _dataclasses
import re import re
import sys as _sys
import types as _types import types as _types
from io import StringIO as _StringIO from io import StringIO as _StringIO
from typing import Any from typing import Any
from typing import Callable from typing import Callable
from typing import Dict from typing import Dict
from typing import IO from typing import IO
from typing import Iterator
from typing import List from typing import List
from typing import Optional
from typing import Set
from typing import Tuple
class _safe_key: class _safe_key:
@ -58,15 +61,13 @@ def _safe_tuple(t):
class PrettyPrinter: class PrettyPrinter:
def __init__( def __init__(
self, self,
indent=1, indent: int = 4,
width=80, width: int = 80,
depth=None, depth: Optional[int] = None,
stream=None,
*, *,
compact=False, sort_dicts: bool = True,
sort_dicts=True, underscore_numbers: bool = False,
underscore_numbers=False, ) -> None:
):
"""Handle pretty printing operations onto a stream using a set of """Handle pretty printing operations onto a stream using a set of
configured parameters. configured parameters.
@ -79,13 +80,6 @@ class PrettyPrinter:
depth depth
The maximum depth to print out nested structures. The maximum depth to print out nested structures.
stream
The desired output stream. If omitted (or false), the standard
output stream available at construction will be used.
compact
If true, several items will be combined in one line.
sort_dicts sort_dicts
If true, dict keys are sorted. If true, dict keys are sorted.
@ -101,32 +95,33 @@ class PrettyPrinter:
self._depth = depth self._depth = depth
self._indent_per_level = indent self._indent_per_level = indent
self._width = width self._width = width
if stream is not None:
self._stream = stream
else:
self._stream = _sys.stdout
self._compact = bool(compact)
self._sort_dicts = sort_dicts self._sort_dicts = sort_dicts
self._underscore_numbers = underscore_numbers self._underscore_numbers = underscore_numbers
def pformat(self, object: Any) -> str: def pformat(self, object: Any) -> str:
sio = _StringIO() sio = _StringIO()
self._format(object, sio, 0, 0, {}, 0) self._format(object, sio, 0, 0, set(), 0)
return sio.getvalue() return sio.getvalue()
def _format(self, object, stream, indent, allowance, context, level): def _format(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
objid = id(object) objid = id(object)
if objid in context: if objid in context:
stream.write(_recursion(object)) stream.write(_recursion(object))
self._recursive = True
self._readable = False
return return
p = self._dispatch.get(type(object).__repr__, None) p = self._dispatch.get(type(object).__repr__, None)
if p is not None: if p is not None:
context[objid] = 1 context.add(objid)
p(self, object, stream, indent, allowance, context, level + 1) p(self, object, stream, indent, allowance, context, level + 1)
del context[objid] context.remove(objid)
elif ( elif (
_dataclasses.is_dataclass(object) _dataclasses.is_dataclass(object)
and not isinstance(object, type) and not isinstance(object, type)
@ -136,17 +131,24 @@ class PrettyPrinter:
hasattr(object.__repr__, "__wrapped__") hasattr(object.__repr__, "__wrapped__")
and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ and "__create_fn__" in object.__repr__.__wrapped__.__qualname__
): ):
context[objid] = 1 context.add(objid)
self._pprint_dataclass( self._pprint_dataclass(
object, stream, indent, allowance, context, level + 1 object, stream, indent, allowance, context, level + 1
) )
del context[objid] context.remove(objid)
else: else:
stream.write(self._repr(object, context, level)) stream.write(self._repr(object, context, level))
def _pprint_dataclass(self, object, stream, indent, allowance, context, level): def _pprint_dataclass(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
cls_name = object.__class__.__name__ cls_name = object.__class__.__name__
indent += len(cls_name) + 1
items = [ items = [
(f.name, getattr(object, f.name)) (f.name, getattr(object, f.name))
for f in _dataclasses.fields(object) for f in _dataclasses.fields(object)
@ -158,63 +160,87 @@ class PrettyPrinter:
_dispatch: Dict[ _dispatch: Dict[
Callable[..., str], Callable[..., str],
Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], str], Callable[["PrettyPrinter", Any, IO[str], int, int, Set[int], int], None],
] = {} ] = {}
def _pprint_dict(self, object, stream, indent, allowance, context, level): def _pprint_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write write = stream.write
write("{") write("{")
if self._indent_per_level > 1: if self._sort_dicts:
write((self._indent_per_level - 1) * " ") items = sorted(object.items(), key=_safe_tuple)
length = len(object) else:
if length: items = object.items()
if self._sort_dicts: self._format_dict_items(items, stream, indent, allowance, context, level)
items = sorted(object.items(), key=_safe_tuple)
else:
items = object.items()
self._format_dict_items(
items, stream, indent, allowance + 1, context, level
)
write("}") write("}")
_dispatch[dict.__repr__] = _pprint_dict _dispatch[dict.__repr__] = _pprint_dict
def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level): def _pprint_ordered_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object): if not len(object):
stream.write(repr(object)) stream.write(repr(object))
return return
cls = object.__class__ cls = object.__class__
stream.write(cls.__name__ + "(") stream.write(cls.__name__ + "(")
self._format( self._pprint_dict(object, stream, indent, allowance, context, level)
list(object.items()),
stream,
indent + len(cls.__name__) + 1,
allowance + 1,
context,
level,
)
stream.write(")") stream.write(")")
_dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
def _pprint_list(self, object, stream, indent, allowance, context, level): def _pprint_list(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("[") stream.write("[")
self._format_items(object, stream, indent, allowance + 1, context, level) self._format_items(object, stream, indent, allowance, context, level)
stream.write("]") stream.write("]")
_dispatch[list.__repr__] = _pprint_list _dispatch[list.__repr__] = _pprint_list
def _pprint_tuple(self, object, stream, indent, allowance, context, level): def _pprint_tuple(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("(") stream.write("(")
endchar = ",)" if len(object) == 1 else ")" self._format_items(object, stream, indent, allowance, context, level)
self._format_items( stream.write(")")
object, stream, indent, allowance + len(endchar), context, level
)
stream.write(endchar)
_dispatch[tuple.__repr__] = _pprint_tuple _dispatch[tuple.__repr__] = _pprint_tuple
def _pprint_set(self, object, stream, indent, allowance, context, level): def _pprint_set(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object): if not len(object):
stream.write(repr(object)) stream.write(repr(object))
return return
@ -225,17 +251,22 @@ class PrettyPrinter:
else: else:
stream.write(typ.__name__ + "({") stream.write(typ.__name__ + "({")
endchar = "})" endchar = "})"
indent += len(typ.__name__) + 1
object = sorted(object, key=_safe_key) object = sorted(object, key=_safe_key)
self._format_items( self._format_items(object, stream, indent, allowance, context, level)
object, stream, indent, allowance + len(endchar), context, level
)
stream.write(endchar) stream.write(endchar)
_dispatch[set.__repr__] = _pprint_set _dispatch[set.__repr__] = _pprint_set
_dispatch[frozenset.__repr__] = _pprint_set _dispatch[frozenset.__repr__] = _pprint_set
def _pprint_str(self, object, stream, indent, allowance, context, level): def _pprint_str(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write write = stream.write
if not len(object): if not len(object):
write(repr(object)) write(repr(object))
@ -286,7 +317,15 @@ class PrettyPrinter:
_dispatch[str.__repr__] = _pprint_str _dispatch[str.__repr__] = _pprint_str
def _pprint_bytes(self, object, stream, indent, allowance, context, level): def _pprint_bytes(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write write = stream.write
if len(object) <= 4: if len(object) <= 4:
write(repr(object)) write(repr(object))
@ -307,7 +346,15 @@ class PrettyPrinter:
_dispatch[bytes.__repr__] = _pprint_bytes _dispatch[bytes.__repr__] = _pprint_bytes
def _pprint_bytearray(self, object, stream, indent, allowance, context, level): def _pprint_bytearray(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
write = stream.write write = stream.write
write("bytearray(") write("bytearray(")
self._pprint_bytes( self._pprint_bytes(
@ -317,23 +364,36 @@ class PrettyPrinter:
_dispatch[bytearray.__repr__] = _pprint_bytearray _dispatch[bytearray.__repr__] = _pprint_bytearray
def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): def _pprint_mappingproxy(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
stream.write("mappingproxy(") stream.write("mappingproxy(")
self._format(object.copy(), stream, indent + 13, allowance + 1, context, level) self._format(object.copy(), stream, indent, allowance, context, level)
stream.write(")") stream.write(")")
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
def _pprint_simplenamespace( def _pprint_simplenamespace(
self, object, stream, indent, allowance, context, level self,
): object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if type(object) is _types.SimpleNamespace: if type(object) is _types.SimpleNamespace:
# The SimpleNamespace repr is "namespace" instead of the class # The SimpleNamespace repr is "namespace" instead of the class
# name, so we do the same here. For subclasses; use the class name. # name, so we do the same here. For subclasses; use the class name.
cls_name = "namespace" cls_name = "namespace"
else: else:
cls_name = object.__class__.__name__ cls_name = object.__class__.__name__
indent += len(cls_name) + 1
items = object.__dict__.items() items = object.__dict__.items()
stream.write(cls_name + "(") stream.write(cls_name + "(")
self._format_namespace_items(items, stream, indent, allowance, context, level) self._format_namespace_items(items, stream, indent, allowance, context, level)
@ -341,33 +401,47 @@ class PrettyPrinter:
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
def _format_dict_items(self, items, stream, indent, allowance, context, level): def _format_dict_items(
write = stream.write self,
indent += self._indent_per_level items: List[Tuple[Any, Any]],
delimnl = ",\n" + " " * indent stream: IO[str],
last_index = len(items) - 1 indent: int,
for i, (key, ent) in enumerate(items): allowance: int,
last = i == last_index context: Set[int],
rep = self._repr(key, context, level) level: int,
write(rep) ) -> None:
write(": ") if not items:
self._format( return
ent,
stream,
indent + len(rep) + 2,
allowance if last else 1,
context,
level,
)
if not last:
write(delimnl)
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
write = stream.write write = stream.write
delimnl = ",\n" + " " * indent item_indent = indent + self._indent_per_level
last_index = len(items) - 1 delimnl = "\n" + " " * item_indent
for i, (key, ent) in enumerate(items): for key, ent in items:
last = i == last_index write(delimnl)
write(self._repr(key, context, level))
write(": ")
self._format(ent, stream, item_indent, 1, context, level)
write(",")
write("\n" + " " * indent)
def _format_namespace_items(
self,
items: List[Tuple[Any, Any]],
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not items:
return
write = stream.write
item_indent = indent + self._indent_per_level
delimnl = "\n" + " " * item_indent
for key, ent in items:
write(delimnl)
write(key) write(key)
write("=") write("=")
if id(ent) in context: if id(ent) in context:
@ -378,174 +452,185 @@ class PrettyPrinter:
self._format( self._format(
ent, ent,
stream, stream,
indent + len(key) + 1, item_indent + len(key) + 1,
allowance if last else 1, 1,
context, context,
level, level,
) )
if not last:
write(delimnl)
def _format_items(self, items, stream, indent, allowance, context, level): write(",")
write = stream.write
indent += self._indent_per_level write("\n" + " " * indent)
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * " ") def _format_items(
delimnl = ",\n" + " " * indent self,
delim = "" items: List[Any],
width = max_width = self._width - indent + 1 stream: IO[str],
it = iter(items) indent: int,
try: allowance: int,
next_ent = next(it) context: Set[int],
except StopIteration: level: int,
) -> None:
if not items:
return return
last = False
while not last:
ent = next_ent
try:
next_ent = next(it)
except StopIteration:
last = True
max_width -= allowance
width -= allowance
if self._compact:
rep = self._repr(ent, context, level)
w = len(rep) + 2
if width < w:
width = max_width
if delim:
delim = delimnl
if width >= w:
width -= w
write(delim)
delim = ", "
write(rep)
continue
write(delim)
delim = delimnl
self._format(ent, stream, indent, allowance if last else 1, context, level)
def _repr(self, object, context, level): write = stream.write
repr, readable, recursive = self.format( item_indent = indent + self._indent_per_level
object, context.copy(), self._depth, level delimnl = "\n" + " " * item_indent
)
if not readable:
self._readable = False
if recursive:
self._recursive = True
return repr
def format(self, object, context, maxlevels, level): for item in items:
"""Format object for a specific context, returning a string write(delimnl)
and flags indicating whether the representation is 'readable' self._format(item, stream, item_indent, 1, context, level)
and whether the object represents a recursive construct. write(",")
"""
write("\n" + " " * indent)
def _repr(self, object: Any, context: Set[int], level: int) -> str:
return self.format(object, context.copy(), self._depth, level)
def format(
self, object: Any, context: Set[int], maxlevels: Optional[int], level: int
) -> str:
return self._safe_repr(object, context, maxlevels, level) return self._safe_repr(object, context, maxlevels, level)
def _pprint_default_dict(self, object, stream, indent, allowance, context, level): def _pprint_default_dict(
if not len(object): self,
stream.write(repr(object)) object: Any,
return stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
rdf = self._repr(object.default_factory, context, level) rdf = self._repr(object.default_factory, context, level)
cls = object.__class__ stream.write(f"{object.__class__.__name__}({rdf}, ")
indent += len(cls.__name__) + 1 self._pprint_dict(object, stream, indent, allowance, context, level)
stream.write(f"{cls.__name__}({rdf},\n{' ' * indent}")
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
stream.write(")") stream.write(")")
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
def _pprint_counter(self, object, stream, indent, allowance, context, level): def _pprint_counter(
if not len(object): self,
stream.write(repr(object)) object: Any,
return stream: IO[str],
cls = object.__class__ indent: int,
stream.write(cls.__name__ + "({") allowance: int,
if self._indent_per_level > 1: context: Set[int],
stream.write((self._indent_per_level - 1) * " ") level: int,
items = object.most_common() ) -> None:
self._format_dict_items( stream.write(object.__class__.__name__ + "(")
items, stream, indent + len(cls.__name__) + 1, allowance + 2, context, level
) if object:
stream.write("})") stream.write("{")
items = object.most_common()
self._format_dict_items(items, stream, indent, allowance, context, level)
stream.write("}")
stream.write(")")
_dispatch[_collections.Counter.__repr__] = _pprint_counter _dispatch[_collections.Counter.__repr__] = _pprint_counter
def _pprint_chain_map(self, object, stream, indent, allowance, context, level): def _pprint_chain_map(
if not len(object.maps): self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])):
stream.write(repr(object)) stream.write(repr(object))
return return
cls = object.__class__
stream.write(cls.__name__ + "(") stream.write(object.__class__.__name__ + "(")
indent += len(cls.__name__) + 1 self._format_items(object.maps, stream, indent, allowance, context, level)
for i, m in enumerate(object.maps): stream.write(")")
if i == len(object.maps) - 1:
self._format(m, stream, indent, allowance + 1, context, level)
stream.write(")")
else:
self._format(m, stream, indent, 1, context, level)
stream.write(",\n" + " " * indent)
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
def _pprint_deque(self, object, stream, indent, allowance, context, level): def _pprint_deque(
if not len(object): self,
stream.write(repr(object)) object: Any,
return stream: IO[str],
cls = object.__class__ indent: int,
stream.write(cls.__name__ + "(") allowance: int,
indent += len(cls.__name__) + 1 context: Set[int],
level: int,
) -> None:
stream.write(object.__class__.__name__ + "(")
if object.maxlen is not None:
stream.write("maxlen=%d, " % object.maxlen)
stream.write("[") stream.write("[")
if object.maxlen is None:
self._format_items(object, stream, indent, allowance + 2, context, level) self._format_items(object, stream, indent, allowance + 1, context, level)
stream.write("])") stream.write("])")
else:
self._format_items(object, stream, indent, 2, context, level)
rml = self._repr(object.maxlen, context, level)
stream.write(f"],\n{' ' * indent}maxlen={rml})")
_dispatch[_collections.deque.__repr__] = _pprint_deque _dispatch[_collections.deque.__repr__] = _pprint_deque
def _pprint_user_dict(self, object, stream, indent, allowance, context, level): def _pprint_user_dict(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1) self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserDict.__repr__] = _pprint_user_dict _dispatch[_collections.UserDict.__repr__] = _pprint_user_dict
def _pprint_user_list(self, object, stream, indent, allowance, context, level): def _pprint_user_list(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1) self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserList.__repr__] = _pprint_user_list _dispatch[_collections.UserList.__repr__] = _pprint_user_list
def _pprint_user_string(self, object, stream, indent, allowance, context, level): def _pprint_user_string(
self,
object: Any,
stream: IO[str],
indent: int,
allowance: int,
context: Set[int],
level: int,
) -> None:
self._format(object.data, stream, indent, allowance, context, level - 1) self._format(object.data, stream, indent, allowance, context, level - 1)
_dispatch[_collections.UserString.__repr__] = _pprint_user_string _dispatch[_collections.UserString.__repr__] = _pprint_user_string
def _safe_repr(self, object, context, maxlevels, level): def _safe_repr(
# Return triple (repr_string, isreadable, isrecursive). self, object: Any, context: Set[int], maxlevels: Optional[int], level: int
) -> str:
typ = type(object) typ = type(object)
if typ in _builtin_scalars: if typ in _builtin_scalars:
return repr(object), True, False return repr(object)
r = getattr(typ, "__repr__", None) r = getattr(typ, "__repr__", None)
if issubclass(typ, int) and r is int.__repr__: if issubclass(typ, int) and r is int.__repr__:
if self._underscore_numbers: if self._underscore_numbers:
return f"{object:_d}", True, False return f"{object:_d}"
else: else:
return repr(object), True, False return repr(object)
if issubclass(typ, dict) and r is dict.__repr__: if issubclass(typ, dict) and r is dict.__repr__:
if not object: if not object:
return "{}", True, False return "{}"
objid = id(object) objid = id(object)
if maxlevels and level >= maxlevels: if maxlevels and level >= maxlevels:
return "{...}", False, objid in context return "{...}"
if objid in context: if objid in context:
return _recursion(object), False, True return _recursion(object)
context[objid] = 1 context.add(objid)
readable = True
recursive = False
components: List[str] = [] components: List[str] = []
append = components.append append = components.append
level += 1 level += 1
@ -554,61 +639,51 @@ class PrettyPrinter:
else: else:
items = object.items() items = object.items()
for k, v in items: for k, v in items:
krepr, kreadable, krecur = self.format(k, context, maxlevels, level) krepr = self.format(k, context, maxlevels, level)
vrepr, vreadable, vrecur = self.format(v, context, maxlevels, level) vrepr = self.format(v, context, maxlevels, level)
append(f"{krepr}: {vrepr}") append(f"{krepr}: {vrepr}")
readable = readable and kreadable and vreadable context.remove(objid)
if krecur or vrecur: return "{%s}" % ", ".join(components)
recursive = True
del context[objid]
return "{%s}" % ", ".join(components), readable, recursive
if (issubclass(typ, list) and r is list.__repr__) or ( if (issubclass(typ, list) and r is list.__repr__) or (
issubclass(typ, tuple) and r is tuple.__repr__ issubclass(typ, tuple) and r is tuple.__repr__
): ):
if issubclass(typ, list): if issubclass(typ, list):
if not object: if not object:
return "[]", True, False return "[]"
format = "[%s]" format = "[%s]"
elif len(object) == 1: elif len(object) == 1:
format = "(%s,)" format = "(%s,)"
else: else:
if not object: if not object:
return "()", True, False return "()"
format = "(%s)" format = "(%s)"
objid = id(object) objid = id(object)
if maxlevels and level >= maxlevels: if maxlevels and level >= maxlevels:
return format % "...", False, objid in context return format % "..."
if objid in context: if objid in context:
return _recursion(object), False, True return _recursion(object)
context[objid] = 1 context.add(objid)
readable = True
recursive = False
components = [] components = []
append = components.append append = components.append
level += 1 level += 1
for o in object: for o in object:
orepr, oreadable, orecur = self.format(o, context, maxlevels, level) orepr = self.format(o, context, maxlevels, level)
append(orepr) append(orepr)
if not oreadable: context.remove(objid)
readable = False return format % ", ".join(components)
if orecur:
recursive = True
del context[objid]
return format % ", ".join(components), readable, recursive
rep = repr(object) return repr(object)
return rep, (rep and not rep.startswith("<")), False
_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) _builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)})
def _recursion(object): def _recursion(object: Any) -> str:
return f"<Recursion on {type(object).__name__} with id={id(object)}>" return f"<Recursion on {type(object).__name__} with id={id(object)}>"
def _wrap_bytes_repr(object, width, allowance): def _wrap_bytes_repr(object: Any, width: int, allowance: int) -> Iterator[str]:
current = b"" current = b""
last = len(object) // 4 * 4 last = len(object) // 4 * 4
for i in range(0, len(object), 4): for i in range(0, len(object), 4):

View File

@ -230,6 +230,8 @@ def assertrepr_compare(
if not explanation: if not explanation:
return None return None
if explanation[0] != "":
explanation = [""] + explanation
return [summary] + explanation return [summary] + explanation
@ -318,18 +320,6 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
return explanation return explanation
def _surrounding_parens_on_own_lines(lines: List[str]) -> None:
"""Move opening/closing parenthesis/bracket to own lines."""
opening = lines[0][:1]
if opening in ["(", "[", "{"]:
lines[0] = " " + lines[0][1:]
lines[:] = [opening] + lines
closing = lines[-1][-1:]
if closing in [")", "]", "}"]:
lines[-1] = lines[-1][:-1] + ","
lines[:] = lines + [closing]
def _compare_eq_iterable( def _compare_eq_iterable(
left: Iterable[Any], left: Iterable[Any],
right: Iterable[Any], right: Iterable[Any],
@ -341,22 +331,10 @@ def _compare_eq_iterable(
# dynamic import to speedup pytest # dynamic import to speedup pytest
import difflib import difflib
left_formatting = pprint.pformat(left).splitlines() left_formatting = PrettyPrinter().pformat(left).splitlines()
right_formatting = pprint.pformat(right).splitlines() right_formatting = PrettyPrinter().pformat(right).splitlines()
# Re-format for different output lengths. explanation = ["", "Full diff:"]
lines_left = len(left_formatting)
lines_right = len(right_formatting)
if lines_left != lines_right:
printer = PrettyPrinter()
left_formatting = printer.pformat(left).splitlines()
right_formatting = printer.pformat(right).splitlines()
if lines_left > 1 or lines_right > 1:
_surrounding_parens_on_own_lines(left_formatting)
_surrounding_parens_on_own_lines(right_formatting)
explanation = ["Full diff:"]
# "right" is the expected base against which we compare "left", # "right" is the expected base against which we compare "left",
# see https://github.com/pytest-dev/pytest/issues/3333 # see https://github.com/pytest-dev/pytest/issues/3333
explanation.extend( explanation.extend(

View File

@ -9,8 +9,8 @@ from _pytest.nodes import Item
from _pytest.stash import StashKey from _pytest.stash import StashKey
fault_handler_original_stderr_fd_key = StashKey[int]()
fault_handler_stderr_fd_key = StashKey[int]() fault_handler_stderr_fd_key = StashKey[int]()
fault_handler_originally_enabled_key = StashKey[bool]()
def pytest_addoption(parser: Parser) -> None: def pytest_addoption(parser: Parser) -> None:
@ -24,8 +24,15 @@ def pytest_addoption(parser: Parser) -> None:
def pytest_configure(config: Config) -> None: def pytest_configure(config: Config) -> None:
import faulthandler import faulthandler
config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno()) # at teardown we want to restore the original faulthandler fileno
config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled() # but faulthandler has no api to return the original fileno
# so here we stash the stderr fileno to be used at teardown
# sys.stderr and sys.__stderr__ may be closed or patched during the session
# so we can't rely on their values being good at that point (#11572).
stderr_fileno = get_stderr_fileno()
if faulthandler.is_enabled():
config.stash[fault_handler_original_stderr_fd_key] = stderr_fileno
config.stash[fault_handler_stderr_fd_key] = os.dup(stderr_fileno)
faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key]) faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key])
@ -37,9 +44,10 @@ def pytest_unconfigure(config: Config) -> None:
if fault_handler_stderr_fd_key in config.stash: if fault_handler_stderr_fd_key in config.stash:
os.close(config.stash[fault_handler_stderr_fd_key]) os.close(config.stash[fault_handler_stderr_fd_key])
del 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.
# Re-enable the faulthandler if it was originally enabled. if fault_handler_original_stderr_fd_key in config.stash:
faulthandler.enable(file=get_stderr_fileno()) faulthandler.enable(config.stash[fault_handler_original_stderr_fd_key])
del config.stash[fault_handler_original_stderr_fd_key]
def get_stderr_fileno() -> int: def get_stderr_fileno() -> int:

View File

@ -564,6 +564,22 @@ class LogCaptureFixture:
self.handler.setLevel(handler_orig_level) self.handler.setLevel(handler_orig_level)
logging.disable(original_disable_level) logging.disable(original_disable_level)
@contextmanager
def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]:
"""Context manager that temporarily adds the given filter to the caplog's
:meth:`handler` for the 'with' statement block, and removes that filter at the
end of the block.
:param filter_: A custom :class:`logging.Filter` object.
.. versionadded:: 7.5
"""
self.handler.addFilter(filter_)
try:
yield
finally:
self.handler.removeFilter(filter_)
@fixture @fixture
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]: def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:

View File

@ -121,13 +121,18 @@ def pytest_configure(config: Config) -> None:
class LsofFdLeakChecker: class LsofFdLeakChecker:
def get_open_files(self) -> List[Tuple[str, str]]: def get_open_files(self) -> List[Tuple[str, str]]:
if sys.version_info >= (3, 11):
# New in Python 3.11, ignores utf-8 mode
encoding = locale.getencoding()
else:
encoding = locale.getpreferredencoding(False)
out = subprocess.run( out = subprocess.run(
("lsof", "-Ffn0", "-p", str(os.getpid())), ("lsof", "-Ffn0", "-p", str(os.getpid())),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
check=True, check=True,
text=True, text=True,
encoding=locale.getpreferredencoding(False), encoding=encoding,
).stdout ).stdout
def isopen(line: str) -> bool: def isopen(line: str) -> bool:

View File

@ -31,6 +31,17 @@ def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("COLUMNS", "80") monkeypatch.setenv("COLUMNS", "80")
@pytest.fixture(autouse=True)
def reset_colors(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Reset all color-related variables to prevent them from affecting internal pytest output
in tests that depend on it.
"""
monkeypatch.delenv("PY_COLORS", raising=False)
monkeypatch.delenv("NO_COLOR", raising=False)
monkeypatch.delenv("FORCE_COLOR", raising=False)
@pytest.hookimpl(wrapper=True, tryfirst=True) @pytest.hookimpl(wrapper=True, tryfirst=True)
def pytest_collection_modifyitems(items) -> Generator[None, None, None]: def pytest_collection_modifyitems(items) -> Generator[None, None, None]:
"""Prefer faster tests. """Prefer faster tests.

View File

@ -40,15 +40,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
DataclassWithOneItem(foo="bar"), DataclassWithOneItem(foo="bar"),
""" """
DataclassWithOneItem(foo='bar') DataclassWithOneItem(
foo='bar',
)
""", """,
id="dataclass-one-item", id="dataclass-one-item",
), ),
pytest.param( pytest.param(
DataclassWithTwoItems(foo="foo", bar="bar"), DataclassWithTwoItems(foo="foo", bar="bar"),
""" """
DataclassWithTwoItems(foo='foo', DataclassWithTwoItems(
bar='bar') foo='foo',
bar='bar',
)
""", """,
id="dataclass-two-items", id="dataclass-two-items",
), ),
@ -60,15 +64,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
{"one": 1}, {"one": 1},
""" """
{'one': 1} {
'one': 1,
}
""", """,
id="dict-one-item", id="dict-one-item",
), ),
pytest.param( pytest.param(
{"one": 1, "two": 2}, {"one": 1, "two": 2},
""" """
{'one': 1, {
'two': 2} 'one': 1,
'two': 2,
}
""", """,
id="dict-two-items", id="dict-two-items",
), ),
@ -76,18 +84,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
OrderedDict({"one": 1}), OrderedDict({"one": 1}),
""" """
OrderedDict([('one', OrderedDict({
1)]) 'one': 1,
})
""", """,
id="ordereddict-one-item", id="ordereddict-one-item",
), ),
pytest.param( pytest.param(
OrderedDict({"one": 1, "two": 2}), OrderedDict({"one": 1, "two": 2}),
""" """
OrderedDict([('one', OrderedDict({
1), 'one': 1,
('two', 'two': 2,
2)]) })
""", """,
id="ordereddict-two-items", id="ordereddict-two-items",
), ),
@ -99,15 +108,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
[1], [1],
""" """
[1] [
1,
]
""", """,
id="list-one-item", id="list-one-item",
), ),
pytest.param( pytest.param(
[1, 2], [1, 2],
""" """
[1, [
2] 1,
2,
]
""", """,
id="list-two-items", id="list-two-items",
), ),
@ -119,15 +132,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
(1,), (1,),
""" """
(1,) (
1,
)
""", """,
id="tuple-one-item", id="tuple-one-item",
), ),
pytest.param( pytest.param(
(1, 2), (1, 2),
""" """
(1, (
2) 1,
2,
)
""", """,
id="tuple-two-items", id="tuple-two-items",
), ),
@ -139,15 +156,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
{1}, {1},
""" """
{1} {
1,
}
""", """,
id="set-one-item", id="set-one-item",
), ),
pytest.param( pytest.param(
{1, 2}, {1, 2},
""" """
{1, {
2} 1,
2,
}
""", """,
id="set-two-items", id="set-two-items",
), ),
@ -159,15 +180,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
MappingProxyType({"one": 1}), MappingProxyType({"one": 1}),
""" """
mappingproxy({'one': 1}) mappingproxy({
'one': 1,
})
""", """,
id="mappingproxy-one-item", id="mappingproxy-one-item",
), ),
pytest.param( pytest.param(
MappingProxyType({"one": 1, "two": 2}), MappingProxyType({"one": 1, "two": 2}),
""" """
mappingproxy({'one': 1, mappingproxy({
'two': 2}) 'one': 1,
'two': 2,
})
""", """,
id="mappingproxy-two-items", id="mappingproxy-two-items",
), ),
@ -179,15 +204,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
SimpleNamespace(one=1), SimpleNamespace(one=1),
""" """
namespace(one=1) namespace(
one=1,
)
""", """,
id="simplenamespace-one-item", id="simplenamespace-one-item",
), ),
pytest.param( pytest.param(
SimpleNamespace(one=1, two=2), SimpleNamespace(one=1, two=2),
""" """
namespace(one=1, namespace(
two=2) one=1,
two=2,
)
""", """,
id="simplenamespace-two-items", id="simplenamespace-two-items",
), ),
@ -197,17 +226,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
defaultdict(str, {"one": "1"}), defaultdict(str, {"one": "1"}),
""" """
defaultdict(<class 'str'>, defaultdict(<class 'str'>, {
{'one': '1'}) 'one': '1',
})
""", """,
id="defaultdict-one-item", id="defaultdict-one-item",
), ),
pytest.param( pytest.param(
defaultdict(str, {"one": "1", "two": "2"}), defaultdict(str, {"one": "1", "two": "2"}),
""" """
defaultdict(<class 'str'>, defaultdict(<class 'str'>, {
{'one': '1', 'one': '1',
'two': '2'}) 'two': '2',
})
""", """,
id="defaultdict-two-items", id="defaultdict-two-items",
), ),
@ -219,15 +250,19 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
Counter("1"), Counter("1"),
""" """
Counter({'1': 1}) Counter({
'1': 1,
})
""", """,
id="counter-one-item", id="counter-one-item",
), ),
pytest.param( pytest.param(
Counter("121"), Counter("121"),
""" """
Counter({'1': 2, Counter({
'2': 1}) '1': 2,
'2': 1,
})
""", """,
id="counter-two-items", id="counter-two-items",
), ),
@ -235,16 +270,26 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
ChainMap({"one": 1, "two": 2}), ChainMap({"one": 1, "two": 2}),
""" """
ChainMap({'one': 1, ChainMap(
'two': 2}) {
'one': 1,
'two': 2,
},
)
""", """,
id="chainmap-one-item", id="chainmap-one-item",
), ),
pytest.param( pytest.param(
ChainMap({"one": 1}, {"two": 2}), ChainMap({"one": 1}, {"two": 2}),
""" """
ChainMap({'one': 1}, ChainMap(
{'two': 2}) {
'one': 1,
},
{
'two': 2,
},
)
""", """,
id="chainmap-two-items", id="chainmap-two-items",
), ),
@ -256,24 +301,29 @@ class DataclassWithTwoItems:
pytest.param( pytest.param(
deque([1]), deque([1]),
""" """
deque([1]) deque([
1,
])
""", """,
id="deque-one-item", id="deque-one-item",
), ),
pytest.param( pytest.param(
deque([1, 2]), deque([1, 2]),
""" """
deque([1, deque([
2]) 1,
2,
])
""", """,
id="deque-two-items", id="deque-two-items",
), ),
pytest.param( pytest.param(
deque([1, 2], maxlen=3), deque([1, 2], maxlen=3),
""" """
deque([1, deque(maxlen=3, [
2], 1,
maxlen=3) 2,
])
""", """,
id="deque-maxlen", id="deque-maxlen",
), ),
@ -293,34 +343,60 @@ class DataclassWithTwoItems:
"tuple": (1, 2), "tuple": (1, 2),
}, },
""" """
{'chainmap': ChainMap({'one': 1}, {
{'two': 2}), 'chainmap': ChainMap(
'counter': Counter({'2': 2, {
'1': 1}), 'one': 1,
'dataclass': DataclassWithTwoItems(foo='foo', },
bar='bar'), {
'defaultdict': defaultdict(<class 'str'>, 'two': 2,
{'one': '1', },
'two': '2'}), ),
'deque': deque([1, 'counter': Counter({
2], '2': 2,
maxlen=3), '1': 1,
'dict': {'one': 1, }),
'two': 2}, 'dataclass': DataclassWithTwoItems(
'list': [1, foo='foo',
2], bar='bar',
'mappingproxy': mappingproxy({'one': 1, ),
'two': 2}), 'defaultdict': defaultdict(<class 'str'>, {
'ordereddict': OrderedDict([('one', 'one': '1',
1), 'two': '2',
('two', }),
2)]), 'deque': deque(maxlen=3, [
'set': {1, 1,
2}, 2,
'simplenamespace': namespace(one=1, ]),
two=2), 'dict': {
'tuple': (1, 'one': 1,
2)} 'two': 2,
},
'list': [
1,
2,
],
'mappingproxy': mappingproxy({
'one': 1,
'two': 2,
}),
'ordereddict': OrderedDict({
'one': 1,
'two': 2,
}),
'set': {
1,
2,
},
'simplenamespace': namespace(
one=1,
two=2,
),
'tuple': (
1,
2,
),
}
""", """,
id="deep-example", id="deep-example",
), ),

View File

@ -144,7 +144,7 @@ def test_change_level_undos_handler_level(pytester: Pytester) -> None:
result.assert_outcomes(passed=3) result.assert_outcomes(passed=3)
def test_with_statement(caplog: pytest.LogCaptureFixture) -> None: def test_with_statement_at_level(caplog: pytest.LogCaptureFixture) -> None:
with caplog.at_level(logging.INFO): with caplog.at_level(logging.INFO):
logger.debug("handler DEBUG level") logger.debug("handler DEBUG level")
logger.info("handler INFO level") logger.info("handler INFO level")
@ -159,7 +159,9 @@ def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
assert "CRITICAL" in caplog.text assert "CRITICAL" in caplog.text
def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None: def test_with_statement_at_level_logging_disabled(
caplog: pytest.LogCaptureFixture,
) -> None:
logging.disable(logging.CRITICAL) logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL assert logging.root.manager.disable == logging.CRITICAL
with caplog.at_level(logging.WARNING): with caplog.at_level(logging.WARNING):
@ -185,6 +187,22 @@ def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> No
assert logging.root.manager.disable == logging.CRITICAL assert logging.root.manager.disable == logging.CRITICAL
def test_with_statement_filtering(caplog: pytest.LogCaptureFixture) -> None:
class TestFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
record.msg = "filtered handler call"
return True
with caplog.at_level(logging.INFO):
with caplog.filtering(TestFilter()):
logger.info("handler call")
logger.info("handler call")
filtered_tuple, unfiltered_tuple = caplog.record_tuples
assert filtered_tuple == ("test_fixture", 20, "filtered handler call")
assert unfiltered_tuple == ("test_fixture", 20, "handler call")
@pytest.mark.parametrize( @pytest.mark.parametrize(
"level_str,expected_disable_level", "level_str,expected_disable_level",
[ [

View File

@ -1,13 +1,13 @@
anyio[curio,trio]==4.0.0 anyio[curio,trio]==4.1.0
django==4.2.7 django==4.2.7
pytest-asyncio==0.21.1 pytest-asyncio==0.23.1
pytest-bdd==7.0.0 pytest-bdd==7.0.1
pytest-cov==4.1.0 pytest-cov==4.1.0
pytest-django==4.7.0 pytest-django==4.7.0
pytest-flakes==4.0.5 pytest-flakes==4.0.5
pytest-html==4.1.1 pytest-html==4.1.1
pytest-mock==3.12.0 pytest-mock==3.12.0
pytest-rerunfailures==12.0 pytest-rerunfailures==13.0
pytest-sugar==0.9.7 pytest-sugar==0.9.7
pytest-trio==0.7.0 pytest-trio==0.7.0
pytest-twisted==1.14.0 pytest-twisted==1.14.0

View File

@ -99,6 +99,7 @@ class TestApprox:
2.0, 2.0,
1.0, 1.0,
[ [
"",
" comparison failed", " comparison failed",
f" Obtained: {SOME_FLOAT}", f" Obtained: {SOME_FLOAT}",
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}", f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
@ -113,6 +114,7 @@ class TestApprox:
"c": 3000000.0, "c": 3000000.0,
}, },
[ [
r"",
r" comparison failed. Mismatched elements: 2 / 3:", r" comparison failed. Mismatched elements: 2 / 3:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -130,6 +132,7 @@ class TestApprox:
"c": None, "c": None,
}, },
[ [
r"",
r" comparison failed. Mismatched elements: 2 / 3:", r" comparison failed. Mismatched elements: 2 / 3:",
r" Max absolute difference: -inf", r" Max absolute difference: -inf",
r" Max relative difference: -inf", r" Max relative difference: -inf",
@ -143,6 +146,7 @@ class TestApprox:
[1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0],
[1.0, 3.0, 3.0, 5.0], [1.0, 3.0, 3.0, 5.0],
[ [
r"",
r" comparison failed. Mismatched elements: 2 / 4:", r" comparison failed. Mismatched elements: 2 / 4:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -156,6 +160,7 @@ class TestApprox:
(1, 2.2, 4), (1, 2.2, 4),
(1, 3.2, 4), (1, 3.2, 4),
[ [
r"",
r" comparison failed. Mismatched elements: 1 / 3:", r" comparison failed. Mismatched elements: 1 / 3:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -169,6 +174,7 @@ class TestApprox:
[0.0], [0.0],
[1.0], [1.0],
[ [
r"",
r" comparison failed. Mismatched elements: 1 / 1:", r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf", r" Max relative difference: inf",
@ -187,6 +193,7 @@ class TestApprox:
a, a,
b, b,
[ [
r"",
r" comparison failed. Mismatched elements: 1 / 20:", r" comparison failed. Mismatched elements: 1 / 20:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -209,6 +216,7 @@ class TestApprox:
] ]
), ),
[ [
r"",
r" comparison failed. Mismatched elements: 3 / 8:", r" comparison failed. Mismatched elements: 3 / 8:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -224,6 +232,7 @@ class TestApprox:
np.array([0.0]), np.array([0.0]),
np.array([1.0]), np.array([1.0]),
[ [
r"",
r" comparison failed. Mismatched elements: 1 / 1:", r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf", r" Max relative difference: inf",
@ -241,6 +250,7 @@ class TestApprox:
message = "\n".join(str(e.value).split("\n")[1:]) message = "\n".join(str(e.value).split("\n")[1:])
assert message == "\n".join( assert message == "\n".join(
[ [
" ",
" Impossible to compare arrays with different shapes.", " Impossible to compare arrays with different shapes.",
" Shapes: (2, 1) and (2, 2)", " Shapes: (2, 1) and (2, 2)",
] ]
@ -251,6 +261,7 @@ class TestApprox:
message = "\n".join(str(e.value).split("\n")[1:]) message = "\n".join(str(e.value).split("\n")[1:])
assert message == "\n".join( assert message == "\n".join(
[ [
" ",
" Impossible to compare lists with different sizes.", " Impossible to compare lists with different sizes.",
" Lengths: 2 and 3", " Lengths: 2 and 3",
] ]
@ -264,6 +275,7 @@ class TestApprox:
2.0, 2.0,
1.0, 1.0,
[ [
"",
" comparison failed", " comparison failed",
f" Obtained: {SOME_FLOAT}", f" Obtained: {SOME_FLOAT}",
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}", f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
@ -277,15 +289,15 @@ class TestApprox:
a, a,
b, b,
[ [
r" comparison failed. Mismatched elements: 20 / 20:", r"^ $",
rf" Max absolute difference: {SOME_FLOAT}", r"^ comparison failed. Mismatched elements: 20 / 20:$",
rf" Max relative difference: {SOME_FLOAT}", rf"^ Max absolute difference: {SOME_FLOAT}$",
r" Index \| Obtained\s+\| Expected", rf"^ Max relative difference: {SOME_FLOAT}$",
rf" \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}", r"^ Index \| Obtained\s+\| Expected\s+$",
rf" \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}", rf"^ \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}$",
rf" \(2,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}...", rf"^ \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}\.\.\.$",
"", "^ $",
rf"\s*...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show", rf"^ ...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show$",
], ],
verbosity_level=0, verbosity_level=0,
) )
@ -294,6 +306,7 @@ class TestApprox:
a, a,
b, b,
[ [
r" ",
r" comparison failed. Mismatched elements: 20 / 20:", r" comparison failed. Mismatched elements: 20 / 20:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
rf" Max relative difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}",
@ -652,6 +665,7 @@ class TestApprox:
{"foo": 42.0}, {"foo": 42.0},
{"foo": 0.0}, {"foo": 0.0},
[ [
r"",
r" comparison failed. Mismatched elements: 1 / 1:", r" comparison failed. Mismatched elements: 1 / 1:",
rf" Max absolute difference: {SOME_FLOAT}", rf" Max absolute difference: {SOME_FLOAT}",
r" Max relative difference: inf", r" Max relative difference: inf",

View File

@ -392,6 +392,7 @@ class TestAssert_reprcompare:
def test_text_diff(self) -> None: def test_text_diff(self) -> None:
assert callequal("spam", "eggs") == [ assert callequal("spam", "eggs") == [
"'spam' == 'eggs'", "'spam' == 'eggs'",
"",
"- eggs", "- eggs",
"+ spam", "+ spam",
] ]
@ -399,7 +400,7 @@ class TestAssert_reprcompare:
def test_text_skipping(self) -> None: def test_text_skipping(self) -> None:
lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs") lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs")
assert lines is not None assert lines is not None
assert "Skipping" in lines[1] assert "Skipping" in lines[2]
for line in lines: for line in lines:
assert "a" * 50 not in line assert "a" * 50 not in line
@ -423,6 +424,7 @@ class TestAssert_reprcompare:
assert diff == [ assert diff == [
"b'spam' == b'eggs'", "b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'", "At index 0 diff: b's' != b'e'",
"Use -v to get more diff", "Use -v to get more diff",
] ]
@ -432,7 +434,9 @@ class TestAssert_reprcompare:
diff = callequal(b"spam", b"eggs", verbose=1) diff = callequal(b"spam", b"eggs", verbose=1)
assert diff == [ assert diff == [
"b'spam' == b'eggs'", "b'spam' == b'eggs'",
"",
"At index 0 diff: b's' != b'e'", "At index 0 diff: b's' != b'e'",
"",
"Full diff:", "Full diff:",
"- b'eggs'", "- b'eggs'",
"+ b'spam'", "+ b'spam'",
@ -451,11 +455,14 @@ class TestAssert_reprcompare:
[0, 2], [0, 2],
""" """
Full diff: Full diff:
- [0, 2] [
0,
- 2,
? ^ ? ^
+ [0, 1] + 1,
? ^ ? ^
""", ]
""",
id="lists", id="lists",
), ),
pytest.param( pytest.param(
@ -463,10 +470,12 @@ class TestAssert_reprcompare:
{0: 2}, {0: 2},
""" """
Full diff: Full diff:
- {0: 2} {
? ^ - 0: 2,
+ {0: 1} ? ^
? ^ + 0: 1,
? ^
}
""", """,
id="dicts", id="dicts",
), ),
@ -475,10 +484,13 @@ class TestAssert_reprcompare:
{0, 2}, {0, 2},
""" """
Full diff: Full diff:
- {0, 2} {
0,
- 2,
? ^ ? ^
+ {0, 1} + 1,
? ^ ? ^
}
""", """,
id="sets", id="sets",
), ),
@ -501,6 +513,7 @@ class TestAssert_reprcompare:
expl = callequal([1, 2], [10, 2], verbose=-1) expl = callequal([1, 2], [10, 2], verbose=-1)
assert expl == [ assert expl == [
"[1, 2] == [10, 2]", "[1, 2] == [10, 2]",
"",
"At index 0 diff: 1 != 10", "At index 0 diff: 1 != 10",
"Use -v to get more diff", "Use -v to get more diff",
] ]
@ -539,26 +552,30 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True) diff = callequal(l1, l2, verbose=True)
assert diff == [ assert diff == [
"['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']", "['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']",
"",
"Right contains one more item: '" + long_d + "'", "Right contains one more item: '" + long_d + "'",
"",
"Full diff:", "Full diff:",
" [", " [",
" 'a',", " 'a',",
" 'b',", " 'b',",
" 'c',", " 'c',",
"- '" + long_d + "',", "- '" + long_d + "',",
" ]", " ]",
] ]
diff = callequal(l2, l1, verbose=True) diff = callequal(l2, l1, verbose=True)
assert diff == [ assert diff == [
"['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']", "['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']",
"",
"Left contains one more item: '" + long_d + "'", "Left contains one more item: '" + long_d + "'",
"",
"Full diff:", "Full diff:",
" [", " [",
" 'a',", " 'a',",
" 'b',", " 'b',",
" 'c',", " 'c',",
"+ '" + long_d + "',", "+ '" + long_d + "',",
" ]", " ]",
] ]
@ -571,13 +588,15 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True) diff = callequal(l1, l2, verbose=True)
assert diff == [ assert diff == [
"['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']", "['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']",
"",
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", "At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
"",
"Full diff:", "Full diff:",
" [", " [",
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", "+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
" 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',", " 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',",
" 'cccccccccccccccccccccccccccccc',", " 'cccccccccccccccccccccccccccccc',",
"- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", "- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
" ]", " ]",
] ]
@ -588,19 +607,21 @@ class TestAssert_reprcompare:
diff = callequal(l1, l2, verbose=True) diff = callequal(l1, l2, verbose=True)
assert diff == [ assert diff == [
"['a', 'aaaaaa...aaaaaaa', ...] == ['should not get wrapped']", "['a', 'aaaaaa...aaaaaaa', ...] == ['should not get wrapped']",
"",
"At index 0 diff: 'a' != 'should not get wrapped'", "At index 0 diff: 'a' != 'should not get wrapped'",
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'", "Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
"",
"Full diff:", "Full diff:",
" [", " [",
"- 'should not get wrapped',", "- 'should not get wrapped',",
"+ 'a',", "+ 'a',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
"+ 'aaaaaaaaaa',", "+ 'aaaaaaaaaa',",
" ]", " ]",
] ]
@ -611,31 +632,45 @@ class TestAssert_reprcompare:
diff = callequal(d1, d2, verbose=True) diff = callequal(d1, d2, verbose=True)
assert diff == [ assert diff == [
"{'common': 1,...1, 'env2': 2}} == {'common': 1,...: {'env1': 1}}", "{'common': 1,...1, 'env2': 2}} == {'common': 1,...: {'env1': 1}}",
"",
"Omitting 1 identical items, use -vv to show", "Omitting 1 identical items, use -vv to show",
"Differing items:", "Differing items:",
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}", "{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
"",
"Full diff:", "Full diff:",
"- {'common': 1, 'env': {'env1': 1}}", " {",
"+ {'common': 1, 'env': {'env1': 1, 'env2': 2}}", " 'common': 1,",
"? +++++++++++", " 'env': {",
" 'env1': 1,",
"+ 'env2': 2,",
" },",
" }",
] ]
long_a = "a" * 80 long_a = "a" * 80
sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 2}} sub = {"long_a": long_a, "sub1": {"long_a": "substring that gets wrapped " * 3}}
d1 = {"env": {"sub": sub}} d1 = {"env": {"sub": sub}}
d2 = {"env": {"sub": sub}, "new": 1} d2 = {"env": {"sub": sub}, "new": 1}
diff = callequal(d1, d2, verbose=True) diff = callequal(d1, d2, verbose=True)
assert diff == [ assert diff == [
"{'env': {'sub... wrapped '}}}} == {'env': {'sub...}}}, 'new': 1}", "{'env': {'sub... wrapped '}}}} == {'env': {'sub...}}}, 'new': 1}",
"",
"Omitting 1 identical items, use -vv to show", "Omitting 1 identical items, use -vv to show",
"Right contains 1 more item:", "Right contains 1 more item:",
"{'new': 1}", "{'new': 1}",
"",
"Full diff:", "Full diff:",
" {", " {",
" 'env': {'sub': {'long_a': '" + long_a + "',", " 'env': {",
" 'sub1': {'long_a': 'substring that gets wrapped substring '", " 'sub': {",
" 'that gets wrapped '}}},", f" 'long_a': '{long_a}',",
"- 'new': 1,", " 'sub1': {",
" 'long_a': 'substring that gets wrapped substring that gets wrapped '",
" 'substring that gets wrapped ',",
" },",
" },",
" },",
"- 'new': 1,",
" }", " }",
] ]
@ -647,7 +682,7 @@ class TestAssert_reprcompare:
def test_dict_omitting(self) -> None: def test_dict_omitting(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}) lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1})
assert lines is not None assert lines is not None
assert lines[1].startswith("Omitting 1 identical item") assert lines[2].startswith("Omitting 1 identical item")
assert "Common items" not in lines assert "Common items" not in lines
for line in lines[1:]: for line in lines[1:]:
assert "b" not in line assert "b" not in line
@ -656,60 +691,109 @@ class TestAssert_reprcompare:
"""Ensure differing items are visible for verbosity=1 (#1512).""" """Ensure differing items are visible for verbosity=1 (#1512)."""
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=1) lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=1)
assert lines is not None assert lines is not None
assert lines[1].startswith("Omitting 1 identical item") assert lines[1] == ""
assert lines[2].startswith("Differing items") assert lines[2].startswith("Omitting 1 identical item")
assert lines[3] == "{'a': 0} != {'a': 1}" assert lines[3].startswith("Differing items")
assert lines[4] == "{'a': 0} != {'a': 1}"
assert "Common items" not in lines assert "Common items" not in lines
def test_dict_omitting_with_verbosity_2(self) -> None: def test_dict_omitting_with_verbosity_2(self) -> None:
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=2) lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=2)
assert lines is not None assert lines is not None
assert lines[1].startswith("Common items:") assert lines[2].startswith("Common items:")
assert "Omitting" not in lines[1] assert "Omitting" not in lines[2]
assert lines[2] == "{'b': 1}" assert lines[3] == "{'b': 1}"
def test_dict_different_items(self) -> None: def test_dict_different_items(self) -> None:
lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2) lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2)
assert lines == [ assert lines == [
"{'a': 0} == {'b': 1, 'c': 2}", "{'a': 0} == {'b': 1, 'c': 2}",
"",
"Left contains 1 more item:", "Left contains 1 more item:",
"{'a': 0}", "{'a': 0}",
"Right contains 2 more items:", "Right contains 2 more items:",
"{'b': 1, 'c': 2}", "{'b': 1, 'c': 2}",
"",
"Full diff:", "Full diff:",
"- {'b': 1, 'c': 2}", " {",
"+ {'a': 0}", "- 'b': 1,",
"? ^ ^",
"+ 'a': 0,",
"? ^ ^",
"- 'c': 2,",
" }",
] ]
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2) lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
assert lines == [ assert lines == [
"{'b': 1, 'c': 2} == {'a': 0}", "{'b': 1, 'c': 2} == {'a': 0}",
"",
"Left contains 2 more items:", "Left contains 2 more items:",
"{'b': 1, 'c': 2}", "{'b': 1, 'c': 2}",
"Right contains 1 more item:", "Right contains 1 more item:",
"{'a': 0}", "{'a': 0}",
"",
"Full diff:", "Full diff:",
"- {'a': 0}", " {",
"+ {'b': 1, 'c': 2}", "- 'a': 0,",
"? ^ ^",
"+ 'b': 1,",
"? ^ ^",
"+ 'c': 2,",
" }",
] ]
def test_sequence_different_items(self) -> None: def test_sequence_different_items(self) -> None:
lines = callequal((1, 2), (3, 4, 5), verbose=2) lines = callequal((1, 2), (3, 4, 5), verbose=2)
assert lines == [ assert lines == [
"(1, 2) == (3, 4, 5)", "(1, 2) == (3, 4, 5)",
"",
"At index 0 diff: 1 != 3", "At index 0 diff: 1 != 3",
"Right contains one more item: 5", "Right contains one more item: 5",
"",
"Full diff:", "Full diff:",
"- (3, 4, 5)", " (",
"+ (1, 2)", "- 3,",
"? ^",
"+ 1,",
"? ^",
"- 4,",
"? ^",
"+ 2,",
"? ^",
"- 5,",
" )",
] ]
lines = callequal((1, 2, 3), (4,), verbose=2) lines = callequal((1, 2, 3), (4,), verbose=2)
assert lines == [ assert lines == [
"(1, 2, 3) == (4,)", "(1, 2, 3) == (4,)",
"",
"At index 0 diff: 1 != 4", "At index 0 diff: 1 != 4",
"Left contains 2 more items, first extra item: 2", "Left contains 2 more items, first extra item: 2",
"",
"Full diff:", "Full diff:",
"- (4,)", " (",
"+ (1, 2, 3)", "- 4,",
"? ^",
"+ 1,",
"? ^",
"+ 2,",
"+ 3,",
" )",
]
lines = callequal((1, 2, 3), (1, 20, 3), verbose=2)
assert lines == [
"(1, 2, 3) == (1, 20, 3)",
"",
"At index 1 diff: 2 != 20",
"",
"Full diff:",
" (",
" 1,",
"- 20,",
"? -",
"+ 2,",
" 3,",
" )",
] ]
def test_set(self) -> None: def test_set(self) -> None:
@ -767,7 +851,7 @@ class TestAssert_reprcompare:
assert expl is not None assert expl is not None
assert expl[0].startswith("{} == <[ValueError") assert expl[0].startswith("{} == <[ValueError")
assert "raised in repr" in expl[0] assert "raised in repr" in expl[0]
assert expl[1:] == [ assert expl[2:] == [
"(pytest_assertion plugin: representation of details failed:" "(pytest_assertion plugin: representation of details failed:"
" {}:{}: ValueError: 42.".format( " {}:{}: ValueError: 42.".format(
__file__, A.__repr__.__code__.co_firstlineno + 1 __file__, A.__repr__.__code__.co_firstlineno + 1
@ -793,6 +877,7 @@ class TestAssert_reprcompare:
def test_unicode(self) -> None: def test_unicode(self) -> None:
assert callequal("£€", "£") == [ assert callequal("£€", "£") == [
"'£€' == '£'", "'£€' == '£'",
"",
"- £", "- £",
"+ £€", "+ £€",
] ]
@ -808,7 +893,7 @@ class TestAssert_reprcompare:
return "\xff" return "\xff"
expl = callequal(A(), "1") expl = callequal(A(), "1")
assert expl == ["ÿ == '1'", "- 1"] assert expl == ["ÿ == '1'", "", "- 1"]
def test_format_nonascii_explanation(self) -> None: def test_format_nonascii_explanation(self) -> None:
assert util.format_explanation("λ") assert util.format_explanation("λ")
@ -831,6 +916,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right) expl = callequal(left, right)
assert expl == [ assert expl == [
r"'hyv\xe4' == 'hyva\u0308'", r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}", f"- {str(right)}",
f"+ {str(left)}", f"+ {str(left)}",
] ]
@ -838,6 +924,7 @@ class TestAssert_reprcompare:
expl = callequal(left, right, verbose=2) expl = callequal(left, right, verbose=2)
assert expl == [ assert expl == [
r"'hyv\xe4' == 'hyva\u0308'", r"'hyv\xe4' == 'hyva\u0308'",
"",
f"- {str(right)}", f"- {str(right)}",
f"+ {str(left)}", f"+ {str(left)}",
] ]
@ -1126,6 +1213,7 @@ class TestAssert_reprcompare_namedtuple:
# Because the types are different, uses the generic sequence matcher. # Because the types are different, uses the generic sequence matcher.
assert lines == [ assert lines == [
"NT1(a=1, b='b') == NT2(a=2, b='b')", "NT1(a=1, b='b') == NT2(a=2, b='b')",
"",
"At index 0 diff: 1 != 2", "At index 0 diff: 1 != 2",
"Use -v to get more diff", "Use -v to get more diff",
] ]
@ -1313,7 +1401,7 @@ class TestTruncateExplanation:
line_count = 7 line_count = 7
line_len = 100 line_len = 100
expected_truncated_lines = 1 expected_truncated_lines = 2
pytester.makepyfile( pytester.makepyfile(
r""" r"""
def test_many_lines(): def test_many_lines():
@ -1333,8 +1421,7 @@ class TestTruncateExplanation:
[ [
"*+ 1*", "*+ 1*",
"*+ 3*", "*+ 3*",
"*+ 5*", "*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines,
"*truncated (%d line hidden)*use*-vv*" % expected_truncated_lines,
] ]
) )
@ -1377,6 +1464,7 @@ def test_rewritten(pytester: Pytester) -> None:
def test_reprcompare_notin() -> None: def test_reprcompare_notin() -> None:
assert callop("not in", "foo", "aaafoobbb") == [ assert callop("not in", "foo", "aaafoobbb") == [
"'foo' not in 'aaafoobbb'", "'foo' not in 'aaafoobbb'",
"",
"'foo' is contained here:", "'foo' is contained here:",
" aaafoobbb", " aaafoobbb",
"? +++", "? +++",
@ -1386,6 +1474,7 @@ def test_reprcompare_notin() -> None:
def test_reprcompare_whitespaces() -> None: def test_reprcompare_whitespaces() -> None:
assert callequal("\r\n", "\n") == [ assert callequal("\r\n", "\n") == [
r"'\r\n' == '\n'", r"'\r\n' == '\n'",
"",
r"Strings contain only whitespace, escaping them using repr()", r"Strings contain only whitespace, escaping them using repr()",
r"- '\n'", r"- '\n'",
r"+ '\r\n'", r"+ '\r\n'",
@ -1844,8 +1933,8 @@ def test_reprcompare_verbose_long() -> None:
assert [0, 1] == [0, 2] assert [0, 1] == [0, 2]
""", """,
[ [
"{bold}{red}E {light-red}- [0, 2]{hl-reset}{endline}{reset}", "{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}",
"{bold}{red}E {light-green}+ [0, 1]{hl-reset}{endline}{reset}", "{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}",
], ],
), ),
( (
@ -1857,8 +1946,8 @@ def test_reprcompare_verbose_long() -> None:
""", """,
[ [
"{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}", "{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}",
"{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}", "{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}",
"{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}",
], ],
), ),
), ),
@ -1917,14 +2006,32 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
f"{p.name} .FFF [100%]", f"{p.name} .FFF [100%]",
"E At index 2 diff: 'grapes' != 'orange'", "E At index 2 diff: 'grapes' != 'orange'",
"E Full diff:", "E Full diff:",
"E - ['banana', 'apple', 'orange', 'melon', 'kiwi']", "E [",
"E ? ^ ^^", "E 'banana',",
"E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']", "E 'apple',",
"E ? ^ ^ +", "E - 'orange',",
"E ? ^ ^^",
"E + 'grapes',",
"E ? ^ ^ +",
"E 'melon',",
"E 'kiwi',",
"E ]",
"E Full diff:", "E Full diff:",
"E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}", "E {",
"E ? - - - - - - - -", "E '0': 0,",
"E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}", "E - '10': 10,",
"E ? - -",
"E + '1': 1,",
"E - '20': 20,",
"E ? - -",
"E + '2': 2,",
"E - '30': 30,",
"E ? - -",
"E + '3': 3,",
"E - '40': 40,",
"E ? - -",
"E + '4': 4,",
"E }",
f"E AssertionError: assert 'hello world' in '{long_text}'", f"E AssertionError: assert 'hello world' in '{long_text}'",
] ]
) )

View File

@ -1959,16 +1959,6 @@ def test_invocation_args(pytester: Pytester) -> None:
], ],
) )
def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None: def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None:
if plugin == "debugging":
# Fixed in xdist (after 1.27.0).
# https://github.com/pytest-dev/pytest-xdist/pull/422
try:
import xdist # noqa: F401
except ImportError:
pass
else:
pytest.skip("does not work with xdist currently")
p = pytester.makepyfile("def test(): pass") p = pytester.makepyfile("def test(): pass")
result = pytester.runpytest(str(p), "-pno:%s" % plugin) result = pytester.runpytest(str(p), "-pno:%s" % plugin)

View File

@ -21,10 +21,14 @@ TESTCASES = [
E assert [1, 4, 3] == [1, 2, 3] E assert [1, 4, 3] == [1, 2, 3]
E At index 1 diff: 4 != 2 E At index 1 diff: 4 != 2
E Full diff: E Full diff:
E - [1, 2, 3] E [
E 1,
E - 2,
E ? ^ E ? ^
E + [1, 4, 3] E + 4,
E ? ^ E ? ^
E 3,
E ]
""", """,
id="Compare lists, one item differs", id="Compare lists, one item differs",
), ),
@ -40,9 +44,11 @@ TESTCASES = [
E assert [1, 2, 3] == [1, 2] E assert [1, 2, 3] == [1, 2]
E Left contains one more item: 3 E Left contains one more item: 3
E Full diff: E Full diff:
E - [1, 2] E [
E + [1, 2, 3] E 1,
E ? +++ E 2,
E + 3,
E ]
""", """,
id="Compare lists, one extra item", id="Compare lists, one extra item",
), ),
@ -59,9 +65,11 @@ TESTCASES = [
E At index 1 diff: 3 != 2 E At index 1 diff: 3 != 2
E Right contains one more item: 3 E Right contains one more item: 3
E Full diff: E Full diff:
E - [1, 2, 3] E [
E ? --- E 1,
E + [1, 3] E - 2,
E 3,
E ]
""", """,
id="Compare lists, one item missing", id="Compare lists, one item missing",
), ),
@ -77,10 +85,14 @@ TESTCASES = [
E assert (1, 4, 3) == (1, 2, 3) E assert (1, 4, 3) == (1, 2, 3)
E At index 1 diff: 4 != 2 E At index 1 diff: 4 != 2
E Full diff: E Full diff:
E - (1, 2, 3) E (
E 1,
E - 2,
E ? ^ E ? ^
E + (1, 4, 3) E + 4,
E ? ^ E ? ^
E 3,
E )
""", """,
id="Compare tuples", id="Compare tuples",
), ),
@ -99,10 +111,12 @@ TESTCASES = [
E Extra items in the right set: E Extra items in the right set:
E 2 E 2
E Full diff: E Full diff:
E - {1, 2, 3} E {
E ? ^ ^ E 1,
E + {1, 3, 4} E - 2,
E ? ^ ^ E 3,
E + 4,
E }
""", """,
id="Compare sets", id="Compare sets",
), ),
@ -123,10 +137,13 @@ TESTCASES = [
E Right contains 1 more item: E Right contains 1 more item:
E {2: 'eggs'} E {2: 'eggs'}
E Full diff: E Full diff:
E - {1: 'spam', 2: 'eggs'} E {
E ? ^ E 1: 'spam',
E + {1: 'spam', 3: 'eggs'} E - 2: 'eggs',
E ? ^ E ? ^
E + 3: 'eggs',
E ? ^
E }
""", """,
id="Compare dicts with differing keys", id="Compare dicts with differing keys",
), ),
@ -145,10 +162,11 @@ TESTCASES = [
E Differing items: E Differing items:
E {2: 'eggs'} != {2: 'bacon'} E {2: 'eggs'} != {2: 'bacon'}
E Full diff: E Full diff:
E - {1: 'spam', 2: 'bacon'} E {
E ? ^^^^^ E 1: 'spam',
E + {1: 'spam', 2: 'eggs'} E - 2: 'bacon',
E ? ^^^^ E + 2: 'eggs',
E }
""", """,
id="Compare dicts with differing values", id="Compare dicts with differing values",
), ),
@ -169,10 +187,11 @@ TESTCASES = [
E Right contains 1 more item: E Right contains 1 more item:
E {3: 'bacon'} E {3: 'bacon'}
E Full diff: E Full diff:
E - {1: 'spam', 3: 'bacon'} E {
E ? ^ ^^^^^ E 1: 'spam',
E + {1: 'spam', 2: 'eggs'} E - 3: 'bacon',
E ? ^ ^^^^ E + 2: 'eggs',
E }
""", """,
id="Compare dicts with differing items", id="Compare dicts with differing items",
), ),

View File

@ -290,10 +290,10 @@ class TestParser:
def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
try: if sys.version_info >= (3, 11):
# 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] encoding = locale.getencoding()
except AttributeError: else:
encoding = locale.getpreferredencoding(False) encoding = locale.getpreferredencoding(False)
try: try:
bash_version = subprocess.run( bash_version = subprocess.run(

View File

@ -1812,7 +1812,7 @@ def test_terminal_no_summary_warnings_header_once(pytester: Pytester) -> None:
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def tr() -> TerminalReporter: def tr() -> TerminalReporter:
config = _pytest.config._prepareconfig() config = _pytest.config._prepareconfig([])
return TerminalReporter(config) return TerminalReporter(config)