Merge branch 'pytest-dev:main' into issue-11037
This commit is contained in:
commit
ebe2257919
|
@ -47,7 +47,7 @@ jobs:
|
|||
path: dist
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
|
|
@ -56,7 +56,7 @@ repos:
|
|||
hooks:
|
||||
- id: python-use-type-annotations
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.7.0
|
||||
rev: v1.7.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: ^(src/|testing/)
|
||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -188,6 +188,7 @@ Javier Romero
|
|||
Jeff Rackauckas
|
||||
Jeff Widman
|
||||
Jenni Rinker
|
||||
Jens Tröger
|
||||
John Eddie Ayson
|
||||
John Litborn
|
||||
John Towler
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
Improved very verbose diff output to color it as a diff instead of only red.
|
||||
|
||||
Improved the error reporting to better separate each section.
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
|||
Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment.
|
|
@ -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.
|
|
@ -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.
|
|
@ -241,7 +241,7 @@ through ``add_color_level()``. Example:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.hookimpl
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_configure(config):
|
||||
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
|
||||
|
||||
|
|
|
@ -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
|
||||
page.
|
||||
|
||||
This list contains 1346 plugins.
|
||||
This list contains 1351 plugins.
|
||||
|
||||
.. 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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-asyncio` Pytest support for asyncio Nov 16, 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` Pytest support for asyncio Nov 27, 2023 4 - Beta pytest (>=7.0.0)
|
||||
: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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0)
|
||||
:pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest
|
||||
:pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Nov 07, 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-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 07, 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-qemu` Make pytest-embedded plugin work with QEMU. Nov 07, 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-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 07, 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` 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 27, 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 27, 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 27, 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 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-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)
|
||||
|
@ -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-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A
|
||||
:pypi:`pytest-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A
|
||||
:pypi:`pytest-env` 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-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)
|
||||
|
@ -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-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-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-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-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-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0)
|
||||
:pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest
|
||||
:pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A
|
||||
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. 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-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
|
||||
|
@ -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-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-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-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-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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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-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)
|
||||
|
@ -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-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A
|
||||
:pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6)
|
||||
:pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. 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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0
|
||||
:pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest
|
||||
:pypi:`pytest-mh` Pytest multihost plugin 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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0)
|
||||
:pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0)
|
||||
:pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 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-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)
|
||||
|
@ -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-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-reana` Pytest fixtures for REANA. Sep 26, 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-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. 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-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)
|
||||
|
@ -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-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-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-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-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
|
||||
|
@ -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-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-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-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-sanity` Dec 07, 2020 N/A N/A
|
||||
:pypi:`pytest-sa-pg` May 14, 2019 N/A N/A
|
||||
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. 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-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-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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-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-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 2023 N/A N/A
|
||||
: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 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-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
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -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-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-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-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
|
||||
|
@ -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-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-venv` py.test fixture for creating a virtual environment Aug 04, 2020 4 - Beta pytest
|
||||
:pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 18, 2023 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 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-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
|
||||
|
@ -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-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest
|
||||
:pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Jan 13, 2023 5 - Production/Stable pytest (>=7.0.0)
|
||||
:pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs 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-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)
|
||||
|
@ -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-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-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-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)
|
||||
|
@ -1694,7 +1699,7 @@ This list contains 1346 plugins.
|
|||
Pytest fixtures to assert anything and something
|
||||
|
||||
:pypi:`pytest-aoc`
|
||||
*last release*: Sep 19, 2023,
|
||||
*last release*: Dec 02, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest ; extra == 'test'
|
||||
|
||||
|
@ -1771,7 +1776,7 @@ This list contains 1346 plugins.
|
|||
pyest results colection plugin
|
||||
|
||||
:pypi:`pytest-arraydiff`
|
||||
*last release*: Nov 15, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest >=4.6
|
||||
|
||||
|
@ -1883,14 +1888,14 @@ This list contains 1346 plugins.
|
|||
Pytest fixtures for async generators
|
||||
|
||||
:pypi:`pytest-asyncio`
|
||||
*last release*: Nov 16, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=7.0.0)
|
||||
|
||||
Pytest support for asyncio
|
||||
|
||||
:pypi:`pytest-asyncio-cooperative`
|
||||
*last release*: Aug 06, 2023,
|
||||
*last release*: Nov 30, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -1918,7 +1923,7 @@ This list contains 1346 plugins.
|
|||
Database testing fixtures using the SQLAlchemy asyncio API
|
||||
|
||||
:pypi:`pytest-atf-allure`
|
||||
*last release*: Oct 22, 2023,
|
||||
*last release*: Nov 29, 2023,
|
||||
*status*: N/A,
|
||||
*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.
|
||||
|
||||
:pypi:`pytest-choose`
|
||||
*last release*: Nov 02, 2023,
|
||||
*last release*: Nov 30, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest >=7.0.0
|
||||
|
||||
|
@ -3801,7 +3806,7 @@ This list contains 1346 plugins.
|
|||
pytest plugin for dogu report
|
||||
|
||||
:pypi:`pytest-dogu-sdk`
|
||||
*last release*: Aug 04, 2023,
|
||||
*last release*: Nov 20, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4018,56 +4023,56 @@ This list contains 1346 plugins.
|
|||
Send execution result email
|
||||
|
||||
:pypi:`pytest-embedded`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest>=7.0
|
||||
|
||||
A pytest plugin that designed for embedded testing.
|
||||
|
||||
:pypi:`pytest-embedded-arduino`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with Arduino.
|
||||
|
||||
:pypi:`pytest-embedded-idf`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with ESP-IDF.
|
||||
|
||||
:pypi:`pytest-embedded-jtag`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with JTAG.
|
||||
|
||||
:pypi:`pytest-embedded-qemu`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with QEMU.
|
||||
|
||||
:pypi:`pytest-embedded-serial`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with Serial.
|
||||
|
||||
:pypi:`pytest-embedded-serial-esp`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
Make pytest-embedded plugin work with Espressif target boards.
|
||||
|
||||
:pypi:`pytest-embedded-wokwi`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 27, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -4137,7 +4142,7 @@ This list contains 1346 plugins.
|
|||
Improvements for pytest (rejected upstream)
|
||||
|
||||
:pypi:`pytest-env`
|
||||
*last release*: Oct 30, 2023,
|
||||
*last release*: Nov 28, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest>=7.4.3
|
||||
|
||||
|
@ -4837,9 +4842,9 @@ This list contains 1346 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-fzf`
|
||||
*last release*: Nov 15, 2023,
|
||||
*status*: 1 - Planning,
|
||||
*requires*: pytest >=7.1.2
|
||||
*last release*: Nov 28, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest >=6.0.0
|
||||
|
||||
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
|
||||
|
||||
: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`
|
||||
*last release*: Feb 25, 2020,
|
||||
*status*: N/A,
|
||||
|
@ -4893,7 +4905,7 @@ This list contains 1346 plugins.
|
|||
For finding/executing Ghost Inspector tests
|
||||
|
||||
:pypi:`pytest-girder`
|
||||
*last release*: Nov 08, 2023,
|
||||
*last release*: Nov 20, 2023,
|
||||
*status*: 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
|
||||
|
||||
: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`
|
||||
*last release*: Oct 09, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
|
@ -5152,7 +5171,7 @@ This list contains 1346 plugins.
|
|||
A pytest plugin for use with homeassistant custom components.
|
||||
|
||||
:pypi:`pytest-homeassistant-custom-component`
|
||||
*last release*: Nov 11, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: pytest ==7.4.3
|
||||
|
||||
|
@ -5173,7 +5192,7 @@ This list contains 1346 plugins.
|
|||
Report on tests that honor constraints, and guard against regressions
|
||||
|
||||
:pypi:`pytest-hot-reloading`
|
||||
*last release*: Jun 23, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -5425,7 +5444,7 @@ This list contains 1346 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-image-snapshot`
|
||||
*last release*: Nov 16, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest >=3.5.0
|
||||
|
||||
|
@ -5488,7 +5507,7 @@ This list contains 1346 plugins.
|
|||
A pytest plugin for writing inline tests.
|
||||
|
||||
:pypi:`pytest-inmanta`
|
||||
*last release*: Aug 03, 2023,
|
||||
*last release*: Nov 29, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -5502,7 +5521,7 @@ This list contains 1346 plugins.
|
|||
Inmanta tests package
|
||||
|
||||
:pypi:`pytest-inmanta-lsm`
|
||||
*last release*: May 17, 2023,
|
||||
*last release*: Nov 29, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -5572,7 +5591,7 @@ This list contains 1346 plugins.
|
|||
Pytest plugin for intercepting outgoing connection requests during pytest run.
|
||||
|
||||
:pypi:`pytest-interface-tester`
|
||||
*last release*: Sep 14, 2023,
|
||||
*last release*: Nov 29, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -6027,7 +6046,7 @@ This list contains 1346 plugins.
|
|||
A pytest plugin that stream output in LITF format
|
||||
|
||||
:pypi:`pytest-litter`
|
||||
*last release*: Aug 08, 2023,
|
||||
*last release*: Nov 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest >=6.1
|
||||
|
||||
|
@ -6377,7 +6396,7 @@ This list contains 1346 plugins.
|
|||
Custom metrics report for pytest
|
||||
|
||||
:pypi:`pytest-mh`
|
||||
*last release*: Sep 27, 2023,
|
||||
*last release*: Nov 21, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -7014,9 +7033,9 @@ This list contains 1346 plugins.
|
|||
A pytest plugin for orchestrating tests
|
||||
|
||||
:pypi:`pytest-order`
|
||||
*last release*: Mar 10, 2023,
|
||||
*last release*: Nov 18, 2023,
|
||||
*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
|
||||
|
||||
|
@ -7188,6 +7207,13 @@ This list contains 1346 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Jul 31, 2018,
|
||||
*status*: N/A,
|
||||
|
@ -7721,7 +7747,7 @@ This list contains 1346 plugins.
|
|||
Record PyMySQL queries and mock with the stored data.
|
||||
|
||||
:pypi:`pytest-pyodide`
|
||||
*last release*: Nov 04, 2023,
|
||||
*last release*: Nov 18, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -7847,9 +7873,9 @@ This list contains 1346 plugins.
|
|||
Pytest plugin for uploading test results to your QA Touch Testrun.
|
||||
|
||||
:pypi:`pytest-qgis`
|
||||
*last release*: Jun 30, 2023,
|
||||
*last release*: Nov 29, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=6.2.5)
|
||||
*requires*: pytest >=6.0
|
||||
|
||||
A pytest plugin for testing QGIS python plugins
|
||||
|
||||
|
@ -7994,14 +8020,14 @@ This list contains 1346 plugins.
|
|||
Test your README.md file
|
||||
|
||||
:pypi:`pytest-reana`
|
||||
*last release*: Sep 26, 2023,
|
||||
*last release*: Nov 30, 2023,
|
||||
*status*: 3 - Alpha,
|
||||
*requires*: N/A
|
||||
|
||||
Pytest fixtures for REANA.
|
||||
|
||||
:pypi:`pytest-recorder`
|
||||
*last release*: Mar 30, 2023,
|
||||
*last release*: Nov 21, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8288,9 +8314,9 @@ This list contains 1346 plugins.
|
|||
Rerun testsuite for a certain time or iterations
|
||||
|
||||
:pypi:`pytest-rerunfailures`
|
||||
*last release*: Jul 05, 2023,
|
||||
*last release*: Nov 22, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest (>=6.2)
|
||||
*requires*: pytest >=7
|
||||
|
||||
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.
|
||||
|
||||
:pypi:`pytest-resilient-circuits`
|
||||
*last release*: Oct 05, 2023,
|
||||
*last release*: Nov 22, 2023,
|
||||
*status*: N/A,
|
||||
*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
|
||||
|
||||
:pypi:`pytest-salt-factories`
|
||||
*last release*: Sep 27, 2023,
|
||||
*last release*: Nov 25, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest (>=6.0.0)
|
||||
|
||||
|
@ -8638,7 +8664,7 @@ This list contains 1346 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-sbase`
|
||||
*last release*: Nov 17, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8687,7 +8713,7 @@ This list contains 1346 plugins.
|
|||
A pytest plugin which allows to (de-)select tests from a file.
|
||||
|
||||
:pypi:`pytest-selenium`
|
||||
*last release*: May 28, 2023,
|
||||
*last release*: Nov 20, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: pytest>=6.0.0
|
||||
|
||||
|
@ -8701,7 +8727,7 @@ This list contains 1346 plugins.
|
|||
pytest plugin to automatically capture screenshots upon selenium webdriver events
|
||||
|
||||
:pypi:`pytest-seleniumbase`
|
||||
*last release*: Nov 17, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -8924,6 +8950,13 @@ This list contains 1346 plugins.
|
|||
|
||||
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`
|
||||
*last release*: Dec 15, 2020,
|
||||
*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.
|
||||
|
||||
:pypi:`pytest-spec2md`
|
||||
*last release*: Sep 15, 2023,
|
||||
*last release*: Nov 21, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>7.0)
|
||||
|
||||
|
@ -9198,14 +9231,14 @@ This list contains 1346 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-splunk-addon`
|
||||
*last release*: Oct 23, 2023,
|
||||
*last release*: Nov 25, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest (>5.4.0,<8)
|
||||
|
||||
A Dynamic test tool for Splunk Apps and Add-ons
|
||||
|
||||
:pypi:`pytest-splunk-addon-ui-smartx`
|
||||
*last release*: Nov 15, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 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
|
||||
|
||||
:pypi:`pytest-subinterpreter`
|
||||
*last release*: Nov 25, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest>=7.0.0
|
||||
|
||||
Run pytest in a subinterpreter
|
||||
|
||||
:pypi:`pytest-subprocess`
|
||||
*last release*: Jan 28, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
|
@ -9667,7 +9707,7 @@ This list contains 1346 plugins.
|
|||
pytest reporting plugin for testlink
|
||||
|
||||
:pypi:`pytest-testmon`
|
||||
*last release*: Nov 07, 2023,
|
||||
*last release*: Nov 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest <8,>=5
|
||||
|
||||
|
@ -10178,7 +10218,7 @@ This list contains 1346 plugins.
|
|||
A Typhoon HIL plugin that facilitates test parameter configuration at runtime
|
||||
|
||||
:pypi:`pytest-typhoon-polarion`
|
||||
*last release*: Nov 17, 2023,
|
||||
*last release*: Dec 01, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: N/A
|
||||
|
||||
|
@ -10353,14 +10393,14 @@ This list contains 1346 plugins.
|
|||
|
||||
|
||||
:pypi:`pytest-venv`
|
||||
*last release*: Aug 04, 2020,
|
||||
*last release*: Nov 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest
|
||||
|
||||
py.test fixture for creating a virtual environment
|
||||
|
||||
:pypi:`pytest-ver`
|
||||
*last release*: Nov 18, 2023,
|
||||
*last release*: Nov 23, 2023,
|
||||
*status*: 4 - Beta,
|
||||
*requires*: pytest
|
||||
|
||||
|
@ -10570,7 +10610,7 @@ This list contains 1346 plugins.
|
|||
A pytest plugin for configuring workflow/pipeline tests using YAML files
|
||||
|
||||
:pypi:`pytest-xdist`
|
||||
*last release*: Nov 11, 2023,
|
||||
*last release*: Nov 21, 2023,
|
||||
*status*: 5 - Production/Stable,
|
||||
*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.
|
||||
|
||||
:pypi:`pytest-yaml-sanmu`
|
||||
*last release*: Jul 03, 2023,
|
||||
*last release*: Nov 30, 2023,
|
||||
*status*: N/A,
|
||||
*requires*: pytest>=7.4.0
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[build-system]
|
||||
requires = [
|
||||
# sync with setup.py until we discard non-pep-517/518
|
||||
"setuptools>=45.0",
|
||||
"setuptools-scm[toml]>=6.2.3",
|
||||
]
|
||||
|
|
|
@ -15,14 +15,17 @@
|
|||
import collections as _collections
|
||||
import dataclasses as _dataclasses
|
||||
import re
|
||||
import sys as _sys
|
||||
import types as _types
|
||||
from io import StringIO as _StringIO
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import IO
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Set
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
class _safe_key:
|
||||
|
@ -58,15 +61,13 @@ def _safe_tuple(t):
|
|||
class PrettyPrinter:
|
||||
def __init__(
|
||||
self,
|
||||
indent=1,
|
||||
width=80,
|
||||
depth=None,
|
||||
stream=None,
|
||||
indent: int = 4,
|
||||
width: int = 80,
|
||||
depth: Optional[int] = None,
|
||||
*,
|
||||
compact=False,
|
||||
sort_dicts=True,
|
||||
underscore_numbers=False,
|
||||
):
|
||||
sort_dicts: bool = True,
|
||||
underscore_numbers: bool = False,
|
||||
) -> None:
|
||||
"""Handle pretty printing operations onto a stream using a set of
|
||||
configured parameters.
|
||||
|
||||
|
@ -79,13 +80,6 @@ class PrettyPrinter:
|
|||
depth
|
||||
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
|
||||
If true, dict keys are sorted.
|
||||
|
||||
|
@ -101,32 +95,33 @@ class PrettyPrinter:
|
|||
self._depth = depth
|
||||
self._indent_per_level = indent
|
||||
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._underscore_numbers = underscore_numbers
|
||||
|
||||
def pformat(self, object: Any) -> str:
|
||||
sio = _StringIO()
|
||||
self._format(object, sio, 0, 0, {}, 0)
|
||||
self._format(object, sio, 0, 0, set(), 0)
|
||||
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)
|
||||
if objid in context:
|
||||
stream.write(_recursion(object))
|
||||
self._recursive = True
|
||||
self._readable = False
|
||||
return
|
||||
|
||||
p = self._dispatch.get(type(object).__repr__, None)
|
||||
if p is not None:
|
||||
context[objid] = 1
|
||||
context.add(objid)
|
||||
p(self, object, stream, indent, allowance, context, level + 1)
|
||||
del context[objid]
|
||||
context.remove(objid)
|
||||
elif (
|
||||
_dataclasses.is_dataclass(object)
|
||||
and not isinstance(object, type)
|
||||
|
@ -136,17 +131,24 @@ class PrettyPrinter:
|
|||
hasattr(object.__repr__, "__wrapped__")
|
||||
and "__create_fn__" in object.__repr__.__wrapped__.__qualname__
|
||||
):
|
||||
context[objid] = 1
|
||||
context.add(objid)
|
||||
self._pprint_dataclass(
|
||||
object, stream, indent, allowance, context, level + 1
|
||||
)
|
||||
del context[objid]
|
||||
context.remove(objid)
|
||||
else:
|
||||
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__
|
||||
indent += len(cls_name) + 1
|
||||
items = [
|
||||
(f.name, getattr(object, f.name))
|
||||
for f in _dataclasses.fields(object)
|
||||
|
@ -158,63 +160,87 @@ class PrettyPrinter:
|
|||
|
||||
_dispatch: Dict[
|
||||
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("{")
|
||||
if self._indent_per_level > 1:
|
||||
write((self._indent_per_level - 1) * " ")
|
||||
length = len(object)
|
||||
if length:
|
||||
if self._sort_dicts:
|
||||
items = sorted(object.items(), key=_safe_tuple)
|
||||
else:
|
||||
items = object.items()
|
||||
self._format_dict_items(
|
||||
items, stream, indent, allowance + 1, context, level
|
||||
)
|
||||
self._format_dict_items(items, stream, indent, allowance, context, level)
|
||||
write("}")
|
||||
|
||||
_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):
|
||||
stream.write(repr(object))
|
||||
return
|
||||
cls = object.__class__
|
||||
stream.write(cls.__name__ + "(")
|
||||
self._format(
|
||||
list(object.items()),
|
||||
stream,
|
||||
indent + len(cls.__name__) + 1,
|
||||
allowance + 1,
|
||||
context,
|
||||
level,
|
||||
)
|
||||
self._pprint_dict(object, stream, indent, allowance, context, level)
|
||||
stream.write(")")
|
||||
|
||||
_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("[")
|
||||
self._format_items(object, stream, indent, allowance + 1, context, level)
|
||||
self._format_items(object, stream, indent, allowance, context, level)
|
||||
stream.write("]")
|
||||
|
||||
_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("(")
|
||||
endchar = ",)" if len(object) == 1 else ")"
|
||||
self._format_items(
|
||||
object, stream, indent, allowance + len(endchar), context, level
|
||||
)
|
||||
stream.write(endchar)
|
||||
self._format_items(object, stream, indent, allowance, context, level)
|
||||
stream.write(")")
|
||||
|
||||
_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):
|
||||
stream.write(repr(object))
|
||||
return
|
||||
|
@ -225,17 +251,22 @@ class PrettyPrinter:
|
|||
else:
|
||||
stream.write(typ.__name__ + "({")
|
||||
endchar = "})"
|
||||
indent += len(typ.__name__) + 1
|
||||
object = sorted(object, key=_safe_key)
|
||||
self._format_items(
|
||||
object, stream, indent, allowance + len(endchar), context, level
|
||||
)
|
||||
self._format_items(object, stream, indent, allowance, context, level)
|
||||
stream.write(endchar)
|
||||
|
||||
_dispatch[set.__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
|
||||
if not len(object):
|
||||
write(repr(object))
|
||||
|
@ -286,7 +317,15 @@ class PrettyPrinter:
|
|||
|
||||
_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
|
||||
if len(object) <= 4:
|
||||
write(repr(object))
|
||||
|
@ -307,7 +346,15 @@ class PrettyPrinter:
|
|||
|
||||
_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("bytearray(")
|
||||
self._pprint_bytes(
|
||||
|
@ -317,23 +364,36 @@ class PrettyPrinter:
|
|||
|
||||
_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(")
|
||||
self._format(object.copy(), stream, indent + 13, allowance + 1, context, level)
|
||||
self._format(object.copy(), stream, indent, allowance, context, level)
|
||||
stream.write(")")
|
||||
|
||||
_dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
|
||||
|
||||
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:
|
||||
# The SimpleNamespace repr is "namespace" instead of the class
|
||||
# name, so we do the same here. For subclasses; use the class name.
|
||||
cls_name = "namespace"
|
||||
else:
|
||||
cls_name = object.__class__.__name__
|
||||
indent += len(cls_name) + 1
|
||||
items = object.__dict__.items()
|
||||
stream.write(cls_name + "(")
|
||||
self._format_namespace_items(items, stream, indent, allowance, context, level)
|
||||
|
@ -341,33 +401,47 @@ class PrettyPrinter:
|
|||
|
||||
_dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
|
||||
|
||||
def _format_dict_items(self, items, stream, indent, allowance, context, level):
|
||||
write = stream.write
|
||||
indent += self._indent_per_level
|
||||
delimnl = ",\n" + " " * indent
|
||||
last_index = len(items) - 1
|
||||
for i, (key, ent) in enumerate(items):
|
||||
last = i == last_index
|
||||
rep = self._repr(key, context, level)
|
||||
write(rep)
|
||||
write(": ")
|
||||
self._format(
|
||||
ent,
|
||||
stream,
|
||||
indent + len(rep) + 2,
|
||||
allowance if last else 1,
|
||||
context,
|
||||
level,
|
||||
)
|
||||
if not last:
|
||||
write(delimnl)
|
||||
def _format_dict_items(
|
||||
self,
|
||||
items: List[Tuple[Any, Any]],
|
||||
stream: IO[str],
|
||||
indent: int,
|
||||
allowance: int,
|
||||
context: Set[int],
|
||||
level: int,
|
||||
) -> None:
|
||||
if not items:
|
||||
return
|
||||
|
||||
def _format_namespace_items(self, items, stream, indent, allowance, context, level):
|
||||
write = stream.write
|
||||
delimnl = ",\n" + " " * indent
|
||||
last_index = len(items) - 1
|
||||
for i, (key, ent) in enumerate(items):
|
||||
last = i == last_index
|
||||
item_indent = indent + self._indent_per_level
|
||||
delimnl = "\n" + " " * item_indent
|
||||
for key, ent in items:
|
||||
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("=")
|
||||
if id(ent) in context:
|
||||
|
@ -378,174 +452,185 @@ class PrettyPrinter:
|
|||
self._format(
|
||||
ent,
|
||||
stream,
|
||||
indent + len(key) + 1,
|
||||
allowance if last else 1,
|
||||
item_indent + len(key) + 1,
|
||||
1,
|
||||
context,
|
||||
level,
|
||||
)
|
||||
if not last:
|
||||
write(delimnl)
|
||||
|
||||
def _format_items(self, items, stream, indent, allowance, context, level):
|
||||
write = stream.write
|
||||
indent += self._indent_per_level
|
||||
if self._indent_per_level > 1:
|
||||
write((self._indent_per_level - 1) * " ")
|
||||
delimnl = ",\n" + " " * indent
|
||||
delim = ""
|
||||
width = max_width = self._width - indent + 1
|
||||
it = iter(items)
|
||||
try:
|
||||
next_ent = next(it)
|
||||
except StopIteration:
|
||||
write(",")
|
||||
|
||||
write("\n" + " " * indent)
|
||||
|
||||
def _format_items(
|
||||
self,
|
||||
items: List[Any],
|
||||
stream: IO[str],
|
||||
indent: int,
|
||||
allowance: int,
|
||||
context: Set[int],
|
||||
level: int,
|
||||
) -> None:
|
||||
if not items:
|
||||
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):
|
||||
repr, readable, recursive = self.format(
|
||||
object, context.copy(), self._depth, level
|
||||
)
|
||||
if not readable:
|
||||
self._readable = False
|
||||
if recursive:
|
||||
self._recursive = True
|
||||
return repr
|
||||
write = stream.write
|
||||
item_indent = indent + self._indent_per_level
|
||||
delimnl = "\n" + " " * item_indent
|
||||
|
||||
def format(self, object, context, maxlevels, level):
|
||||
"""Format object for a specific context, returning a string
|
||||
and flags indicating whether the representation is 'readable'
|
||||
and whether the object represents a recursive construct.
|
||||
"""
|
||||
for item in items:
|
||||
write(delimnl)
|
||||
self._format(item, stream, item_indent, 1, context, level)
|
||||
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)
|
||||
|
||||
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
|
||||
if not len(object):
|
||||
stream.write(repr(object))
|
||||
return
|
||||
def _pprint_default_dict(
|
||||
self,
|
||||
object: Any,
|
||||
stream: IO[str],
|
||||
indent: int,
|
||||
allowance: int,
|
||||
context: Set[int],
|
||||
level: int,
|
||||
) -> None:
|
||||
rdf = self._repr(object.default_factory, context, level)
|
||||
cls = object.__class__
|
||||
indent += len(cls.__name__) + 1
|
||||
stream.write(f"{cls.__name__}({rdf},\n{' ' * indent}")
|
||||
self._pprint_dict(object, stream, indent, allowance + 1, context, level)
|
||||
stream.write(f"{object.__class__.__name__}({rdf}, ")
|
||||
self._pprint_dict(object, stream, indent, allowance, context, level)
|
||||
stream.write(")")
|
||||
|
||||
_dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
|
||||
|
||||
def _pprint_counter(self, object, stream, indent, allowance, context, level):
|
||||
if not len(object):
|
||||
stream.write(repr(object))
|
||||
return
|
||||
cls = object.__class__
|
||||
stream.write(cls.__name__ + "({")
|
||||
if self._indent_per_level > 1:
|
||||
stream.write((self._indent_per_level - 1) * " ")
|
||||
def _pprint_counter(
|
||||
self,
|
||||
object: Any,
|
||||
stream: IO[str],
|
||||
indent: int,
|
||||
allowance: int,
|
||||
context: Set[int],
|
||||
level: int,
|
||||
) -> None:
|
||||
stream.write(object.__class__.__name__ + "(")
|
||||
|
||||
if object:
|
||||
stream.write("{")
|
||||
items = object.most_common()
|
||||
self._format_dict_items(
|
||||
items, stream, indent + len(cls.__name__) + 1, allowance + 2, context, level
|
||||
)
|
||||
stream.write("})")
|
||||
self._format_dict_items(items, stream, indent, allowance, context, level)
|
||||
stream.write("}")
|
||||
|
||||
stream.write(")")
|
||||
|
||||
_dispatch[_collections.Counter.__repr__] = _pprint_counter
|
||||
|
||||
def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
|
||||
if not len(object.maps):
|
||||
def _pprint_chain_map(
|
||||
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))
|
||||
return
|
||||
cls = object.__class__
|
||||
stream.write(cls.__name__ + "(")
|
||||
indent += len(cls.__name__) + 1
|
||||
for i, m in enumerate(object.maps):
|
||||
if i == len(object.maps) - 1:
|
||||
self._format(m, stream, indent, allowance + 1, context, level)
|
||||
|
||||
stream.write(object.__class__.__name__ + "(")
|
||||
self._format_items(object.maps, stream, indent, allowance, context, level)
|
||||
stream.write(")")
|
||||
else:
|
||||
self._format(m, stream, indent, 1, context, level)
|
||||
stream.write(",\n" + " " * indent)
|
||||
|
||||
_dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
|
||||
|
||||
def _pprint_deque(self, object, stream, indent, allowance, context, level):
|
||||
if not len(object):
|
||||
stream.write(repr(object))
|
||||
return
|
||||
cls = object.__class__
|
||||
stream.write(cls.__name__ + "(")
|
||||
indent += len(cls.__name__) + 1
|
||||
def _pprint_deque(
|
||||
self,
|
||||
object: Any,
|
||||
stream: IO[str],
|
||||
indent: int,
|
||||
allowance: int,
|
||||
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("[")
|
||||
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("])")
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
_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)
|
||||
|
||||
_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)
|
||||
|
||||
_dispatch[_collections.UserString.__repr__] = _pprint_user_string
|
||||
|
||||
def _safe_repr(self, object, context, maxlevels, level):
|
||||
# Return triple (repr_string, isreadable, isrecursive).
|
||||
def _safe_repr(
|
||||
self, object: Any, context: Set[int], maxlevels: Optional[int], level: int
|
||||
) -> str:
|
||||
typ = type(object)
|
||||
if typ in _builtin_scalars:
|
||||
return repr(object), True, False
|
||||
return repr(object)
|
||||
|
||||
r = getattr(typ, "__repr__", None)
|
||||
|
||||
if issubclass(typ, int) and r is int.__repr__:
|
||||
if self._underscore_numbers:
|
||||
return f"{object:_d}", True, False
|
||||
return f"{object:_d}"
|
||||
else:
|
||||
return repr(object), True, False
|
||||
return repr(object)
|
||||
|
||||
if issubclass(typ, dict) and r is dict.__repr__:
|
||||
if not object:
|
||||
return "{}", True, False
|
||||
return "{}"
|
||||
objid = id(object)
|
||||
if maxlevels and level >= maxlevels:
|
||||
return "{...}", False, objid in context
|
||||
return "{...}"
|
||||
if objid in context:
|
||||
return _recursion(object), False, True
|
||||
context[objid] = 1
|
||||
readable = True
|
||||
recursive = False
|
||||
return _recursion(object)
|
||||
context.add(objid)
|
||||
components: List[str] = []
|
||||
append = components.append
|
||||
level += 1
|
||||
|
@ -554,61 +639,51 @@ class PrettyPrinter:
|
|||
else:
|
||||
items = object.items()
|
||||
for k, v in items:
|
||||
krepr, kreadable, krecur = self.format(k, context, maxlevels, level)
|
||||
vrepr, vreadable, vrecur = self.format(v, context, maxlevels, level)
|
||||
krepr = self.format(k, context, maxlevels, level)
|
||||
vrepr = self.format(v, context, maxlevels, level)
|
||||
append(f"{krepr}: {vrepr}")
|
||||
readable = readable and kreadable and vreadable
|
||||
if krecur or vrecur:
|
||||
recursive = True
|
||||
del context[objid]
|
||||
return "{%s}" % ", ".join(components), readable, recursive
|
||||
context.remove(objid)
|
||||
return "{%s}" % ", ".join(components)
|
||||
|
||||
if (issubclass(typ, list) and r is list.__repr__) or (
|
||||
issubclass(typ, tuple) and r is tuple.__repr__
|
||||
):
|
||||
if issubclass(typ, list):
|
||||
if not object:
|
||||
return "[]", True, False
|
||||
return "[]"
|
||||
format = "[%s]"
|
||||
elif len(object) == 1:
|
||||
format = "(%s,)"
|
||||
else:
|
||||
if not object:
|
||||
return "()", True, False
|
||||
return "()"
|
||||
format = "(%s)"
|
||||
objid = id(object)
|
||||
if maxlevels and level >= maxlevels:
|
||||
return format % "...", False, objid in context
|
||||
return format % "..."
|
||||
if objid in context:
|
||||
return _recursion(object), False, True
|
||||
context[objid] = 1
|
||||
readable = True
|
||||
recursive = False
|
||||
return _recursion(object)
|
||||
context.add(objid)
|
||||
components = []
|
||||
append = components.append
|
||||
level += 1
|
||||
for o in object:
|
||||
orepr, oreadable, orecur = self.format(o, context, maxlevels, level)
|
||||
orepr = self.format(o, context, maxlevels, level)
|
||||
append(orepr)
|
||||
if not oreadable:
|
||||
readable = False
|
||||
if orecur:
|
||||
recursive = True
|
||||
del context[objid]
|
||||
return format % ", ".join(components), readable, recursive
|
||||
context.remove(objid)
|
||||
return format % ", ".join(components)
|
||||
|
||||
rep = repr(object)
|
||||
return rep, (rep and not rep.startswith("<")), False
|
||||
return repr(object)
|
||||
|
||||
|
||||
_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)}>"
|
||||
|
||||
|
||||
def _wrap_bytes_repr(object, width, allowance):
|
||||
def _wrap_bytes_repr(object: Any, width: int, allowance: int) -> Iterator[str]:
|
||||
current = b""
|
||||
last = len(object) // 4 * 4
|
||||
for i in range(0, len(object), 4):
|
||||
|
|
|
@ -230,6 +230,8 @@ def assertrepr_compare(
|
|||
if not explanation:
|
||||
return None
|
||||
|
||||
if explanation[0] != "":
|
||||
explanation = [""] + explanation
|
||||
return [summary] + explanation
|
||||
|
||||
|
||||
|
@ -318,18 +320,6 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
|
|||
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(
|
||||
left: Iterable[Any],
|
||||
right: Iterable[Any],
|
||||
|
@ -341,22 +331,10 @@ def _compare_eq_iterable(
|
|||
# dynamic import to speedup pytest
|
||||
import difflib
|
||||
|
||||
left_formatting = pprint.pformat(left).splitlines()
|
||||
right_formatting = pprint.pformat(right).splitlines()
|
||||
left_formatting = PrettyPrinter().pformat(left).splitlines()
|
||||
right_formatting = PrettyPrinter().pformat(right).splitlines()
|
||||
|
||||
# Re-format for different output lengths.
|
||||
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:"]
|
||||
explanation = ["", "Full diff:"]
|
||||
# "right" is the expected base against which we compare "left",
|
||||
# see https://github.com/pytest-dev/pytest/issues/3333
|
||||
explanation.extend(
|
||||
|
|
|
@ -9,8 +9,8 @@ from _pytest.nodes import Item
|
|||
from _pytest.stash import StashKey
|
||||
|
||||
|
||||
fault_handler_original_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:
|
||||
|
@ -24,8 +24,15 @@ def pytest_addoption(parser: Parser) -> None:
|
|||
def pytest_configure(config: Config) -> None:
|
||||
import faulthandler
|
||||
|
||||
config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno())
|
||||
config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled()
|
||||
# at teardown we want to restore the original faulthandler fileno
|
||||
# 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])
|
||||
|
||||
|
||||
|
@ -37,9 +44,10 @@ def pytest_unconfigure(config: Config) -> None:
|
|||
if fault_handler_stderr_fd_key in config.stash:
|
||||
os.close(config.stash[fault_handler_stderr_fd_key])
|
||||
del config.stash[fault_handler_stderr_fd_key]
|
||||
if config.stash.get(fault_handler_originally_enabled_key, False):
|
||||
# Re-enable the faulthandler if it was originally enabled.
|
||||
faulthandler.enable(file=get_stderr_fileno())
|
||||
if fault_handler_original_stderr_fd_key in config.stash:
|
||||
faulthandler.enable(config.stash[fault_handler_original_stderr_fd_key])
|
||||
del config.stash[fault_handler_original_stderr_fd_key]
|
||||
|
||||
|
||||
def get_stderr_fileno() -> int:
|
||||
|
|
|
@ -564,6 +564,22 @@ class LogCaptureFixture:
|
|||
self.handler.setLevel(handler_orig_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
|
||||
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:
|
||||
|
|
|
@ -121,13 +121,18 @@ def pytest_configure(config: Config) -> None:
|
|||
|
||||
class LsofFdLeakChecker:
|
||||
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(
|
||||
("lsof", "-Ffn0", "-p", str(os.getpid())),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True,
|
||||
text=True,
|
||||
encoding=locale.getpreferredencoding(False),
|
||||
encoding=encoding,
|
||||
).stdout
|
||||
|
||||
def isopen(line: str) -> bool:
|
||||
|
|
|
@ -31,6 +31,17 @@ def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None:
|
|||
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)
|
||||
def pytest_collection_modifyitems(items) -> Generator[None, None, None]:
|
||||
"""Prefer faster tests.
|
||||
|
|
|
@ -40,15 +40,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
DataclassWithOneItem(foo="bar"),
|
||||
"""
|
||||
DataclassWithOneItem(foo='bar')
|
||||
DataclassWithOneItem(
|
||||
foo='bar',
|
||||
)
|
||||
""",
|
||||
id="dataclass-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
DataclassWithTwoItems(foo="foo", bar="bar"),
|
||||
"""
|
||||
DataclassWithTwoItems(foo='foo',
|
||||
bar='bar')
|
||||
DataclassWithTwoItems(
|
||||
foo='foo',
|
||||
bar='bar',
|
||||
)
|
||||
""",
|
||||
id="dataclass-two-items",
|
||||
),
|
||||
|
@ -60,15 +64,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
{"one": 1},
|
||||
"""
|
||||
{'one': 1}
|
||||
{
|
||||
'one': 1,
|
||||
}
|
||||
""",
|
||||
id="dict-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
{"one": 1, "two": 2},
|
||||
"""
|
||||
{'one': 1,
|
||||
'two': 2}
|
||||
{
|
||||
'one': 1,
|
||||
'two': 2,
|
||||
}
|
||||
""",
|
||||
id="dict-two-items",
|
||||
),
|
||||
|
@ -76,18 +84,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
OrderedDict({"one": 1}),
|
||||
"""
|
||||
OrderedDict([('one',
|
||||
1)])
|
||||
OrderedDict({
|
||||
'one': 1,
|
||||
})
|
||||
""",
|
||||
id="ordereddict-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
OrderedDict({"one": 1, "two": 2}),
|
||||
"""
|
||||
OrderedDict([('one',
|
||||
1),
|
||||
('two',
|
||||
2)])
|
||||
OrderedDict({
|
||||
'one': 1,
|
||||
'two': 2,
|
||||
})
|
||||
""",
|
||||
id="ordereddict-two-items",
|
||||
),
|
||||
|
@ -99,15 +108,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
[1],
|
||||
"""
|
||||
[1]
|
||||
[
|
||||
1,
|
||||
]
|
||||
""",
|
||||
id="list-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
[1, 2],
|
||||
"""
|
||||
[1,
|
||||
2]
|
||||
[
|
||||
1,
|
||||
2,
|
||||
]
|
||||
""",
|
||||
id="list-two-items",
|
||||
),
|
||||
|
@ -119,15 +132,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
(1,),
|
||||
"""
|
||||
(1,)
|
||||
(
|
||||
1,
|
||||
)
|
||||
""",
|
||||
id="tuple-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
(1, 2),
|
||||
"""
|
||||
(1,
|
||||
2)
|
||||
(
|
||||
1,
|
||||
2,
|
||||
)
|
||||
""",
|
||||
id="tuple-two-items",
|
||||
),
|
||||
|
@ -139,15 +156,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
{1},
|
||||
"""
|
||||
{1}
|
||||
{
|
||||
1,
|
||||
}
|
||||
""",
|
||||
id="set-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
{1, 2},
|
||||
"""
|
||||
{1,
|
||||
2}
|
||||
{
|
||||
1,
|
||||
2,
|
||||
}
|
||||
""",
|
||||
id="set-two-items",
|
||||
),
|
||||
|
@ -159,15 +180,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
MappingProxyType({"one": 1}),
|
||||
"""
|
||||
mappingproxy({'one': 1})
|
||||
mappingproxy({
|
||||
'one': 1,
|
||||
})
|
||||
""",
|
||||
id="mappingproxy-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
MappingProxyType({"one": 1, "two": 2}),
|
||||
"""
|
||||
mappingproxy({'one': 1,
|
||||
'two': 2})
|
||||
mappingproxy({
|
||||
'one': 1,
|
||||
'two': 2,
|
||||
})
|
||||
""",
|
||||
id="mappingproxy-two-items",
|
||||
),
|
||||
|
@ -179,15 +204,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
SimpleNamespace(one=1),
|
||||
"""
|
||||
namespace(one=1)
|
||||
namespace(
|
||||
one=1,
|
||||
)
|
||||
""",
|
||||
id="simplenamespace-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
SimpleNamespace(one=1, two=2),
|
||||
"""
|
||||
namespace(one=1,
|
||||
two=2)
|
||||
namespace(
|
||||
one=1,
|
||||
two=2,
|
||||
)
|
||||
""",
|
||||
id="simplenamespace-two-items",
|
||||
),
|
||||
|
@ -197,17 +226,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
defaultdict(str, {"one": "1"}),
|
||||
"""
|
||||
defaultdict(<class 'str'>,
|
||||
{'one': '1'})
|
||||
defaultdict(<class 'str'>, {
|
||||
'one': '1',
|
||||
})
|
||||
""",
|
||||
id="defaultdict-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
defaultdict(str, {"one": "1", "two": "2"}),
|
||||
"""
|
||||
defaultdict(<class 'str'>,
|
||||
{'one': '1',
|
||||
'two': '2'})
|
||||
defaultdict(<class 'str'>, {
|
||||
'one': '1',
|
||||
'two': '2',
|
||||
})
|
||||
""",
|
||||
id="defaultdict-two-items",
|
||||
),
|
||||
|
@ -219,15 +250,19 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
Counter("1"),
|
||||
"""
|
||||
Counter({'1': 1})
|
||||
Counter({
|
||||
'1': 1,
|
||||
})
|
||||
""",
|
||||
id="counter-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
Counter("121"),
|
||||
"""
|
||||
Counter({'1': 2,
|
||||
'2': 1})
|
||||
Counter({
|
||||
'1': 2,
|
||||
'2': 1,
|
||||
})
|
||||
""",
|
||||
id="counter-two-items",
|
||||
),
|
||||
|
@ -235,16 +270,26 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
ChainMap({"one": 1, "two": 2}),
|
||||
"""
|
||||
ChainMap({'one': 1,
|
||||
'two': 2})
|
||||
ChainMap(
|
||||
{
|
||||
'one': 1,
|
||||
'two': 2,
|
||||
},
|
||||
)
|
||||
""",
|
||||
id="chainmap-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
ChainMap({"one": 1}, {"two": 2}),
|
||||
"""
|
||||
ChainMap({'one': 1},
|
||||
{'two': 2})
|
||||
ChainMap(
|
||||
{
|
||||
'one': 1,
|
||||
},
|
||||
{
|
||||
'two': 2,
|
||||
},
|
||||
)
|
||||
""",
|
||||
id="chainmap-two-items",
|
||||
),
|
||||
|
@ -256,24 +301,29 @@ class DataclassWithTwoItems:
|
|||
pytest.param(
|
||||
deque([1]),
|
||||
"""
|
||||
deque([1])
|
||||
deque([
|
||||
1,
|
||||
])
|
||||
""",
|
||||
id="deque-one-item",
|
||||
),
|
||||
pytest.param(
|
||||
deque([1, 2]),
|
||||
"""
|
||||
deque([1,
|
||||
2])
|
||||
deque([
|
||||
1,
|
||||
2,
|
||||
])
|
||||
""",
|
||||
id="deque-two-items",
|
||||
),
|
||||
pytest.param(
|
||||
deque([1, 2], maxlen=3),
|
||||
"""
|
||||
deque([1,
|
||||
2],
|
||||
maxlen=3)
|
||||
deque(maxlen=3, [
|
||||
1,
|
||||
2,
|
||||
])
|
||||
""",
|
||||
id="deque-maxlen",
|
||||
),
|
||||
|
@ -293,34 +343,60 @@ class DataclassWithTwoItems:
|
|||
"tuple": (1, 2),
|
||||
},
|
||||
"""
|
||||
{'chainmap': ChainMap({'one': 1},
|
||||
{'two': 2}),
|
||||
'counter': Counter({'2': 2,
|
||||
'1': 1}),
|
||||
'dataclass': DataclassWithTwoItems(foo='foo',
|
||||
bar='bar'),
|
||||
'defaultdict': defaultdict(<class 'str'>,
|
||||
{'one': '1',
|
||||
'two': '2'}),
|
||||
'deque': deque([1,
|
||||
2],
|
||||
maxlen=3),
|
||||
'dict': {'one': 1,
|
||||
'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)}
|
||||
{
|
||||
'chainmap': ChainMap(
|
||||
{
|
||||
'one': 1,
|
||||
},
|
||||
{
|
||||
'two': 2,
|
||||
},
|
||||
),
|
||||
'counter': Counter({
|
||||
'2': 2,
|
||||
'1': 1,
|
||||
}),
|
||||
'dataclass': DataclassWithTwoItems(
|
||||
foo='foo',
|
||||
bar='bar',
|
||||
),
|
||||
'defaultdict': defaultdict(<class 'str'>, {
|
||||
'one': '1',
|
||||
'two': '2',
|
||||
}),
|
||||
'deque': deque(maxlen=3, [
|
||||
1,
|
||||
2,
|
||||
]),
|
||||
'dict': {
|
||||
'one': 1,
|
||||
'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",
|
||||
),
|
||||
|
|
|
@ -144,7 +144,7 @@ def test_change_level_undos_handler_level(pytester: Pytester) -> None:
|
|||
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):
|
||||
logger.debug("handler DEBUG level")
|
||||
logger.info("handler INFO level")
|
||||
|
@ -159,7 +159,9 @@ def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
|
|||
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)
|
||||
assert logging.root.manager.disable == logging.CRITICAL
|
||||
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
|
||||
|
||||
|
||||
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(
|
||||
"level_str,expected_disable_level",
|
||||
[
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
anyio[curio,trio]==4.0.0
|
||||
anyio[curio,trio]==4.1.0
|
||||
django==4.2.7
|
||||
pytest-asyncio==0.21.1
|
||||
pytest-bdd==7.0.0
|
||||
pytest-asyncio==0.23.1
|
||||
pytest-bdd==7.0.1
|
||||
pytest-cov==4.1.0
|
||||
pytest-django==4.7.0
|
||||
pytest-flakes==4.0.5
|
||||
pytest-html==4.1.1
|
||||
pytest-mock==3.12.0
|
||||
pytest-rerunfailures==12.0
|
||||
pytest-rerunfailures==13.0
|
||||
pytest-sugar==0.9.7
|
||||
pytest-trio==0.7.0
|
||||
pytest-twisted==1.14.0
|
||||
|
|
|
@ -99,6 +99,7 @@ class TestApprox:
|
|||
2.0,
|
||||
1.0,
|
||||
[
|
||||
"",
|
||||
" comparison failed",
|
||||
f" Obtained: {SOME_FLOAT}",
|
||||
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
|
||||
|
@ -113,6 +114,7 @@ class TestApprox:
|
|||
"c": 3000000.0,
|
||||
},
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 2 / 3:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -130,6 +132,7 @@ class TestApprox:
|
|||
"c": None,
|
||||
},
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 2 / 3:",
|
||||
r" Max absolute difference: -inf",
|
||||
r" Max relative difference: -inf",
|
||||
|
@ -143,6 +146,7 @@ class TestApprox:
|
|||
[1.0, 2.0, 3.0, 4.0],
|
||||
[1.0, 3.0, 3.0, 5.0],
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 2 / 4:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -156,6 +160,7 @@ class TestApprox:
|
|||
(1, 2.2, 4),
|
||||
(1, 3.2, 4),
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 1 / 3:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -169,6 +174,7 @@ class TestApprox:
|
|||
[0.0],
|
||||
[1.0],
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 1 / 1:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
r" Max relative difference: inf",
|
||||
|
@ -187,6 +193,7 @@ class TestApprox:
|
|||
a,
|
||||
b,
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 1 / 20:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -209,6 +216,7 @@ class TestApprox:
|
|||
]
|
||||
),
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 3 / 8:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -224,6 +232,7 @@ class TestApprox:
|
|||
np.array([0.0]),
|
||||
np.array([1.0]),
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 1 / 1:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
r" Max relative difference: inf",
|
||||
|
@ -241,6 +250,7 @@ class TestApprox:
|
|||
message = "\n".join(str(e.value).split("\n")[1:])
|
||||
assert message == "\n".join(
|
||||
[
|
||||
" ",
|
||||
" Impossible to compare arrays with different shapes.",
|
||||
" Shapes: (2, 1) and (2, 2)",
|
||||
]
|
||||
|
@ -251,6 +261,7 @@ class TestApprox:
|
|||
message = "\n".join(str(e.value).split("\n")[1:])
|
||||
assert message == "\n".join(
|
||||
[
|
||||
" ",
|
||||
" Impossible to compare lists with different sizes.",
|
||||
" Lengths: 2 and 3",
|
||||
]
|
||||
|
@ -264,6 +275,7 @@ class TestApprox:
|
|||
2.0,
|
||||
1.0,
|
||||
[
|
||||
"",
|
||||
" comparison failed",
|
||||
f" Obtained: {SOME_FLOAT}",
|
||||
f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}",
|
||||
|
@ -277,15 +289,15 @@ class TestApprox:
|
|||
a,
|
||||
b,
|
||||
[
|
||||
r" comparison failed. Mismatched elements: 20 / 20:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
r" Index \| Obtained\s+\| Expected",
|
||||
rf" \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}",
|
||||
rf" \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}",
|
||||
rf" \(2,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}...",
|
||||
"",
|
||||
rf"\s*...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show",
|
||||
r"^ $",
|
||||
r"^ comparison failed. Mismatched elements: 20 / 20:$",
|
||||
rf"^ Max absolute difference: {SOME_FLOAT}$",
|
||||
rf"^ Max relative difference: {SOME_FLOAT}$",
|
||||
r"^ Index \| Obtained\s+\| Expected\s+$",
|
||||
rf"^ \(0,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}$",
|
||||
rf"^ \(1,\)\s+\| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}e-{SOME_INT}\.\.\.$",
|
||||
"^ $",
|
||||
rf"^ ...Full output truncated \({SOME_INT} lines hidden\), use '-vv' to show$",
|
||||
],
|
||||
verbosity_level=0,
|
||||
)
|
||||
|
@ -294,6 +306,7 @@ class TestApprox:
|
|||
a,
|
||||
b,
|
||||
[
|
||||
r" ",
|
||||
r" comparison failed. Mismatched elements: 20 / 20:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
rf" Max relative difference: {SOME_FLOAT}",
|
||||
|
@ -652,6 +665,7 @@ class TestApprox:
|
|||
{"foo": 42.0},
|
||||
{"foo": 0.0},
|
||||
[
|
||||
r"",
|
||||
r" comparison failed. Mismatched elements: 1 / 1:",
|
||||
rf" Max absolute difference: {SOME_FLOAT}",
|
||||
r" Max relative difference: inf",
|
||||
|
|
|
@ -392,6 +392,7 @@ class TestAssert_reprcompare:
|
|||
def test_text_diff(self) -> None:
|
||||
assert callequal("spam", "eggs") == [
|
||||
"'spam' == 'eggs'",
|
||||
"",
|
||||
"- eggs",
|
||||
"+ spam",
|
||||
]
|
||||
|
@ -399,7 +400,7 @@ class TestAssert_reprcompare:
|
|||
def test_text_skipping(self) -> None:
|
||||
lines = callequal("a" * 50 + "spam", "a" * 50 + "eggs")
|
||||
assert lines is not None
|
||||
assert "Skipping" in lines[1]
|
||||
assert "Skipping" in lines[2]
|
||||
for line in lines:
|
||||
assert "a" * 50 not in line
|
||||
|
||||
|
@ -423,6 +424,7 @@ class TestAssert_reprcompare:
|
|||
|
||||
assert diff == [
|
||||
"b'spam' == b'eggs'",
|
||||
"",
|
||||
"At index 0 diff: b's' != b'e'",
|
||||
"Use -v to get more diff",
|
||||
]
|
||||
|
@ -432,7 +434,9 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(b"spam", b"eggs", verbose=1)
|
||||
assert diff == [
|
||||
"b'spam' == b'eggs'",
|
||||
"",
|
||||
"At index 0 diff: b's' != b'e'",
|
||||
"",
|
||||
"Full diff:",
|
||||
"- b'eggs'",
|
||||
"+ b'spam'",
|
||||
|
@ -451,10 +455,13 @@ class TestAssert_reprcompare:
|
|||
[0, 2],
|
||||
"""
|
||||
Full diff:
|
||||
- [0, 2]
|
||||
[
|
||||
0,
|
||||
- 2,
|
||||
? ^
|
||||
+ [0, 1]
|
||||
+ 1,
|
||||
? ^
|
||||
]
|
||||
""",
|
||||
id="lists",
|
||||
),
|
||||
|
@ -463,10 +470,12 @@ class TestAssert_reprcompare:
|
|||
{0: 2},
|
||||
"""
|
||||
Full diff:
|
||||
- {0: 2}
|
||||
{
|
||||
- 0: 2,
|
||||
? ^
|
||||
+ {0: 1}
|
||||
+ 0: 1,
|
||||
? ^
|
||||
}
|
||||
""",
|
||||
id="dicts",
|
||||
),
|
||||
|
@ -475,10 +484,13 @@ class TestAssert_reprcompare:
|
|||
{0, 2},
|
||||
"""
|
||||
Full diff:
|
||||
- {0, 2}
|
||||
{
|
||||
0,
|
||||
- 2,
|
||||
? ^
|
||||
+ {0, 1}
|
||||
+ 1,
|
||||
? ^
|
||||
}
|
||||
""",
|
||||
id="sets",
|
||||
),
|
||||
|
@ -501,6 +513,7 @@ class TestAssert_reprcompare:
|
|||
expl = callequal([1, 2], [10, 2], verbose=-1)
|
||||
assert expl == [
|
||||
"[1, 2] == [10, 2]",
|
||||
"",
|
||||
"At index 0 diff: 1 != 10",
|
||||
"Use -v to get more diff",
|
||||
]
|
||||
|
@ -539,7 +552,9 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(l1, l2, verbose=True)
|
||||
assert diff == [
|
||||
"['a', 'b', 'c'] == ['a', 'b', 'c...dddddddddddd']",
|
||||
"",
|
||||
"Right contains one more item: '" + long_d + "'",
|
||||
"",
|
||||
"Full diff:",
|
||||
" [",
|
||||
" 'a',",
|
||||
|
@ -552,7 +567,9 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(l2, l1, verbose=True)
|
||||
assert diff == [
|
||||
"['a', 'b', 'c...dddddddddddd'] == ['a', 'b', 'c']",
|
||||
"",
|
||||
"Left contains one more item: '" + long_d + "'",
|
||||
"",
|
||||
"Full diff:",
|
||||
" [",
|
||||
" 'a',",
|
||||
|
@ -571,7 +588,9 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(l1, l2, verbose=True)
|
||||
assert diff == [
|
||||
"['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']",
|
||||
"",
|
||||
"At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
|
||||
"",
|
||||
"Full diff:",
|
||||
" [",
|
||||
"+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',",
|
||||
|
@ -588,8 +607,10 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(l1, l2, verbose=True)
|
||||
assert diff == [
|
||||
"['a', 'aaaaaa...aaaaaaa', ...] == ['should not get wrapped']",
|
||||
"",
|
||||
"At index 0 diff: 'a' != 'should not get wrapped'",
|
||||
"Left contains 7 more items, first extra item: 'aaaaaaaaaa'",
|
||||
"",
|
||||
"Full diff:",
|
||||
" [",
|
||||
"- 'should not get wrapped',",
|
||||
|
@ -611,30 +632,44 @@ class TestAssert_reprcompare:
|
|||
diff = callequal(d1, d2, verbose=True)
|
||||
assert diff == [
|
||||
"{'common': 1,...1, 'env2': 2}} == {'common': 1,...: {'env1': 1}}",
|
||||
"",
|
||||
"Omitting 1 identical items, use -vv to show",
|
||||
"Differing items:",
|
||||
"{'env': {'env1': 1, 'env2': 2}} != {'env': {'env1': 1}}",
|
||||
"",
|
||||
"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
|
||||
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}}
|
||||
d2 = {"env": {"sub": sub}, "new": 1}
|
||||
diff = callequal(d1, d2, verbose=True)
|
||||
assert diff == [
|
||||
"{'env': {'sub... wrapped '}}}} == {'env': {'sub...}}}, 'new': 1}",
|
||||
"",
|
||||
"Omitting 1 identical items, use -vv to show",
|
||||
"Right contains 1 more item:",
|
||||
"{'new': 1}",
|
||||
"",
|
||||
"Full diff:",
|
||||
" {",
|
||||
" 'env': {'sub': {'long_a': '" + long_a + "',",
|
||||
" 'sub1': {'long_a': 'substring that gets wrapped substring '",
|
||||
" 'that gets wrapped '}}},",
|
||||
" 'env': {",
|
||||
" 'sub': {",
|
||||
f" 'long_a': '{long_a}',",
|
||||
" '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:
|
||||
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1})
|
||||
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
|
||||
for line in lines[1:]:
|
||||
assert "b" not in line
|
||||
|
@ -656,60 +691,109 @@ class TestAssert_reprcompare:
|
|||
"""Ensure differing items are visible for verbosity=1 (#1512)."""
|
||||
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=1)
|
||||
assert lines is not None
|
||||
assert lines[1].startswith("Omitting 1 identical item")
|
||||
assert lines[2].startswith("Differing items")
|
||||
assert lines[3] == "{'a': 0} != {'a': 1}"
|
||||
assert lines[1] == ""
|
||||
assert lines[2].startswith("Omitting 1 identical item")
|
||||
assert lines[3].startswith("Differing items")
|
||||
assert lines[4] == "{'a': 0} != {'a': 1}"
|
||||
assert "Common items" not in lines
|
||||
|
||||
def test_dict_omitting_with_verbosity_2(self) -> None:
|
||||
lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}, verbose=2)
|
||||
assert lines is not None
|
||||
assert lines[1].startswith("Common items:")
|
||||
assert "Omitting" not in lines[1]
|
||||
assert lines[2] == "{'b': 1}"
|
||||
assert lines[2].startswith("Common items:")
|
||||
assert "Omitting" not in lines[2]
|
||||
assert lines[3] == "{'b': 1}"
|
||||
|
||||
def test_dict_different_items(self) -> None:
|
||||
lines = callequal({"a": 0}, {"b": 1, "c": 2}, verbose=2)
|
||||
assert lines == [
|
||||
"{'a': 0} == {'b': 1, 'c': 2}",
|
||||
"",
|
||||
"Left contains 1 more item:",
|
||||
"{'a': 0}",
|
||||
"Right contains 2 more items:",
|
||||
"{'b': 1, 'c': 2}",
|
||||
"",
|
||||
"Full diff:",
|
||||
"- {'b': 1, 'c': 2}",
|
||||
"+ {'a': 0}",
|
||||
" {",
|
||||
"- 'b': 1,",
|
||||
"? ^ ^",
|
||||
"+ 'a': 0,",
|
||||
"? ^ ^",
|
||||
"- 'c': 2,",
|
||||
" }",
|
||||
]
|
||||
lines = callequal({"b": 1, "c": 2}, {"a": 0}, verbose=2)
|
||||
assert lines == [
|
||||
"{'b': 1, 'c': 2} == {'a': 0}",
|
||||
"",
|
||||
"Left contains 2 more items:",
|
||||
"{'b': 1, 'c': 2}",
|
||||
"Right contains 1 more item:",
|
||||
"{'a': 0}",
|
||||
"",
|
||||
"Full diff:",
|
||||
"- {'a': 0}",
|
||||
"+ {'b': 1, 'c': 2}",
|
||||
" {",
|
||||
"- 'a': 0,",
|
||||
"? ^ ^",
|
||||
"+ 'b': 1,",
|
||||
"? ^ ^",
|
||||
"+ 'c': 2,",
|
||||
" }",
|
||||
]
|
||||
|
||||
def test_sequence_different_items(self) -> None:
|
||||
lines = callequal((1, 2), (3, 4, 5), verbose=2)
|
||||
assert lines == [
|
||||
"(1, 2) == (3, 4, 5)",
|
||||
"",
|
||||
"At index 0 diff: 1 != 3",
|
||||
"Right contains one more item: 5",
|
||||
"",
|
||||
"Full diff:",
|
||||
"- (3, 4, 5)",
|
||||
"+ (1, 2)",
|
||||
" (",
|
||||
"- 3,",
|
||||
"? ^",
|
||||
"+ 1,",
|
||||
"? ^",
|
||||
"- 4,",
|
||||
"? ^",
|
||||
"+ 2,",
|
||||
"? ^",
|
||||
"- 5,",
|
||||
" )",
|
||||
]
|
||||
lines = callequal((1, 2, 3), (4,), verbose=2)
|
||||
assert lines == [
|
||||
"(1, 2, 3) == (4,)",
|
||||
"",
|
||||
"At index 0 diff: 1 != 4",
|
||||
"Left contains 2 more items, first extra item: 2",
|
||||
"",
|
||||
"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:
|
||||
|
@ -767,7 +851,7 @@ class TestAssert_reprcompare:
|
|||
assert expl is not None
|
||||
assert expl[0].startswith("{} == <[ValueError")
|
||||
assert "raised in repr" in expl[0]
|
||||
assert expl[1:] == [
|
||||
assert expl[2:] == [
|
||||
"(pytest_assertion plugin: representation of details failed:"
|
||||
" {}:{}: ValueError: 42.".format(
|
||||
__file__, A.__repr__.__code__.co_firstlineno + 1
|
||||
|
@ -793,6 +877,7 @@ class TestAssert_reprcompare:
|
|||
def test_unicode(self) -> None:
|
||||
assert callequal("£€", "£") == [
|
||||
"'£€' == '£'",
|
||||
"",
|
||||
"- £",
|
||||
"+ £€",
|
||||
]
|
||||
|
@ -808,7 +893,7 @@ class TestAssert_reprcompare:
|
|||
return "\xff"
|
||||
|
||||
expl = callequal(A(), "1")
|
||||
assert expl == ["ÿ == '1'", "- 1"]
|
||||
assert expl == ["ÿ == '1'", "", "- 1"]
|
||||
|
||||
def test_format_nonascii_explanation(self) -> None:
|
||||
assert util.format_explanation("λ")
|
||||
|
@ -831,6 +916,7 @@ class TestAssert_reprcompare:
|
|||
expl = callequal(left, right)
|
||||
assert expl == [
|
||||
r"'hyv\xe4' == 'hyva\u0308'",
|
||||
"",
|
||||
f"- {str(right)}",
|
||||
f"+ {str(left)}",
|
||||
]
|
||||
|
@ -838,6 +924,7 @@ class TestAssert_reprcompare:
|
|||
expl = callequal(left, right, verbose=2)
|
||||
assert expl == [
|
||||
r"'hyv\xe4' == 'hyva\u0308'",
|
||||
"",
|
||||
f"- {str(right)}",
|
||||
f"+ {str(left)}",
|
||||
]
|
||||
|
@ -1126,6 +1213,7 @@ class TestAssert_reprcompare_namedtuple:
|
|||
# Because the types are different, uses the generic sequence matcher.
|
||||
assert lines == [
|
||||
"NT1(a=1, b='b') == NT2(a=2, b='b')",
|
||||
"",
|
||||
"At index 0 diff: 1 != 2",
|
||||
"Use -v to get more diff",
|
||||
]
|
||||
|
@ -1313,7 +1401,7 @@ class TestTruncateExplanation:
|
|||
|
||||
line_count = 7
|
||||
line_len = 100
|
||||
expected_truncated_lines = 1
|
||||
expected_truncated_lines = 2
|
||||
pytester.makepyfile(
|
||||
r"""
|
||||
def test_many_lines():
|
||||
|
@ -1333,8 +1421,7 @@ class TestTruncateExplanation:
|
|||
[
|
||||
"*+ 1*",
|
||||
"*+ 3*",
|
||||
"*+ 5*",
|
||||
"*truncated (%d line hidden)*use*-vv*" % expected_truncated_lines,
|
||||
"*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines,
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -1377,6 +1464,7 @@ def test_rewritten(pytester: Pytester) -> None:
|
|||
def test_reprcompare_notin() -> None:
|
||||
assert callop("not in", "foo", "aaafoobbb") == [
|
||||
"'foo' not in 'aaafoobbb'",
|
||||
"",
|
||||
"'foo' is contained here:",
|
||||
" aaafoobbb",
|
||||
"? +++",
|
||||
|
@ -1386,6 +1474,7 @@ def test_reprcompare_notin() -> None:
|
|||
def test_reprcompare_whitespaces() -> None:
|
||||
assert callequal("\r\n", "\n") == [
|
||||
r"'\r\n' == '\n'",
|
||||
"",
|
||||
r"Strings contain only whitespace, escaping them using repr()",
|
||||
r"- '\n'",
|
||||
r"+ '\r\n'",
|
||||
|
@ -1844,8 +1933,8 @@ def test_reprcompare_verbose_long() -> None:
|
|||
assert [0, 1] == [0, 2]
|
||||
""",
|
||||
[
|
||||
"{bold}{red}E {light-red}- [0, 2]{hl-reset}{endline}{reset}",
|
||||
"{bold}{red}E {light-green}+ [0, 1]{hl-reset}{endline}{reset}",
|
||||
"{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}",
|
||||
"{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}",
|
||||
],
|
||||
),
|
||||
(
|
||||
|
@ -1917,14 +2006,32 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
|
|||
f"{p.name} .FFF [100%]",
|
||||
"E At index 2 diff: 'grapes' != 'orange'",
|
||||
"E Full diff:",
|
||||
"E - ['banana', 'apple', 'orange', 'melon', 'kiwi']",
|
||||
"E [",
|
||||
"E 'banana',",
|
||||
"E 'apple',",
|
||||
"E - 'orange',",
|
||||
"E ? ^ ^^",
|
||||
"E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']",
|
||||
"E + 'grapes',",
|
||||
"E ? ^ ^ +",
|
||||
"E 'melon',",
|
||||
"E 'kiwi',",
|
||||
"E ]",
|
||||
"E Full diff:",
|
||||
"E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}",
|
||||
"E ? - - - - - - - -",
|
||||
"E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}",
|
||||
"E {",
|
||||
"E '0': 0,",
|
||||
"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}'",
|
||||
]
|
||||
)
|
||||
|
|
|
@ -1959,16 +1959,6 @@ def test_invocation_args(pytester: Pytester) -> 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")
|
||||
result = pytester.runpytest(str(p), "-pno:%s" % plugin)
|
||||
|
||||
|
|
|
@ -21,10 +21,14 @@ TESTCASES = [
|
|||
E assert [1, 4, 3] == [1, 2, 3]
|
||||
E At index 1 diff: 4 != 2
|
||||
E Full diff:
|
||||
E - [1, 2, 3]
|
||||
E [
|
||||
E 1,
|
||||
E - 2,
|
||||
E ? ^
|
||||
E + [1, 4, 3]
|
||||
E + 4,
|
||||
E ? ^
|
||||
E 3,
|
||||
E ]
|
||||
""",
|
||||
id="Compare lists, one item differs",
|
||||
),
|
||||
|
@ -40,9 +44,11 @@ TESTCASES = [
|
|||
E assert [1, 2, 3] == [1, 2]
|
||||
E Left contains one more item: 3
|
||||
E Full diff:
|
||||
E - [1, 2]
|
||||
E + [1, 2, 3]
|
||||
E ? +++
|
||||
E [
|
||||
E 1,
|
||||
E 2,
|
||||
E + 3,
|
||||
E ]
|
||||
""",
|
||||
id="Compare lists, one extra item",
|
||||
),
|
||||
|
@ -59,9 +65,11 @@ TESTCASES = [
|
|||
E At index 1 diff: 3 != 2
|
||||
E Right contains one more item: 3
|
||||
E Full diff:
|
||||
E - [1, 2, 3]
|
||||
E ? ---
|
||||
E + [1, 3]
|
||||
E [
|
||||
E 1,
|
||||
E - 2,
|
||||
E 3,
|
||||
E ]
|
||||
""",
|
||||
id="Compare lists, one item missing",
|
||||
),
|
||||
|
@ -77,10 +85,14 @@ TESTCASES = [
|
|||
E assert (1, 4, 3) == (1, 2, 3)
|
||||
E At index 1 diff: 4 != 2
|
||||
E Full diff:
|
||||
E - (1, 2, 3)
|
||||
E (
|
||||
E 1,
|
||||
E - 2,
|
||||
E ? ^
|
||||
E + (1, 4, 3)
|
||||
E + 4,
|
||||
E ? ^
|
||||
E 3,
|
||||
E )
|
||||
""",
|
||||
id="Compare tuples",
|
||||
),
|
||||
|
@ -99,10 +111,12 @@ TESTCASES = [
|
|||
E Extra items in the right set:
|
||||
E 2
|
||||
E Full diff:
|
||||
E - {1, 2, 3}
|
||||
E ? ^ ^
|
||||
E + {1, 3, 4}
|
||||
E ? ^ ^
|
||||
E {
|
||||
E 1,
|
||||
E - 2,
|
||||
E 3,
|
||||
E + 4,
|
||||
E }
|
||||
""",
|
||||
id="Compare sets",
|
||||
),
|
||||
|
@ -123,10 +137,13 @@ TESTCASES = [
|
|||
E Right contains 1 more item:
|
||||
E {2: 'eggs'}
|
||||
E Full diff:
|
||||
E - {1: 'spam', 2: 'eggs'}
|
||||
E {
|
||||
E 1: 'spam',
|
||||
E - 2: 'eggs',
|
||||
E ? ^
|
||||
E + {1: 'spam', 3: 'eggs'}
|
||||
E + 3: 'eggs',
|
||||
E ? ^
|
||||
E }
|
||||
""",
|
||||
id="Compare dicts with differing keys",
|
||||
),
|
||||
|
@ -145,10 +162,11 @@ TESTCASES = [
|
|||
E Differing items:
|
||||
E {2: 'eggs'} != {2: 'bacon'}
|
||||
E Full diff:
|
||||
E - {1: 'spam', 2: 'bacon'}
|
||||
E ? ^^^^^
|
||||
E + {1: 'spam', 2: 'eggs'}
|
||||
E ? ^^^^
|
||||
E {
|
||||
E 1: 'spam',
|
||||
E - 2: 'bacon',
|
||||
E + 2: 'eggs',
|
||||
E }
|
||||
""",
|
||||
id="Compare dicts with differing values",
|
||||
),
|
||||
|
@ -169,10 +187,11 @@ TESTCASES = [
|
|||
E Right contains 1 more item:
|
||||
E {3: 'bacon'}
|
||||
E Full diff:
|
||||
E - {1: 'spam', 3: 'bacon'}
|
||||
E ? ^ ^^^^^
|
||||
E + {1: 'spam', 2: 'eggs'}
|
||||
E ? ^ ^^^^
|
||||
E {
|
||||
E 1: 'spam',
|
||||
E - 3: 'bacon',
|
||||
E + 2: 'eggs',
|
||||
E }
|
||||
""",
|
||||
id="Compare dicts with differing items",
|
||||
),
|
||||
|
|
|
@ -290,10 +290,10 @@ class TestParser:
|
|||
|
||||
|
||||
def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
|
||||
try:
|
||||
if sys.version_info >= (3, 11):
|
||||
# New in Python 3.11, ignores utf-8 mode
|
||||
encoding = locale.getencoding() # type: ignore[attr-defined]
|
||||
except AttributeError:
|
||||
encoding = locale.getencoding()
|
||||
else:
|
||||
encoding = locale.getpreferredencoding(False)
|
||||
try:
|
||||
bash_version = subprocess.run(
|
||||
|
|
|
@ -1812,7 +1812,7 @@ def test_terminal_no_summary_warnings_header_once(pytester: Pytester) -> None:
|
|||
|
||||
@pytest.fixture(scope="session")
|
||||
def tr() -> TerminalReporter:
|
||||
config = _pytest.config._prepareconfig()
|
||||
config = _pytest.config._prepareconfig([])
|
||||
return TerminalReporter(config)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue